From 74a0db975ffa40905b216b90dd773fcea4b7d36a Mon Sep 17 00:00:00 2001 From: Vignesh Date: Mon, 12 Jun 2017 22:42:56 +1000 Subject: [PATCH 01/14] cargo fmt --- build.rs | 3 +- src/app.rs | 23 +- src/badge.rs | 60 ++-- src/bin/delete-crate.rs | 62 ++-- src/bin/delete-version.rs | 40 ++- src/bin/fill-in-user-id.rs | 23 +- src/bin/populate.rs | 8 +- src/bin/server.rs | 18 +- src/bin/transfer-crates.rs | 18 +- src/bin/update-downloads.rs | 217 +++++++++---- src/categories.rs | 67 ++-- src/category.rs | 249 ++++++++------ src/db.rs | 52 +-- src/dependency.rs | 116 ++++--- src/dist.rs | 22 +- src/download.rs | 18 +- src/git.rs | 65 ++-- src/http.rs | 34 +- src/keyword.rs | 71 ++-- src/krate.rs | 623 +++++++++++++++++++++--------------- src/lib.rs | 41 +-- src/owner.rs | 98 +++--- src/tests/all.rs | 215 +++++++------ src/tests/badge.rs | 240 ++++---------- src/tests/category.rs | 46 +-- src/tests/git.rs | 27 +- src/tests/keyword.rs | 20 +- src/tests/krate.rs | 388 +++++++++++++--------- src/tests/record.rs | 173 +++++----- src/tests/team.rs | 170 +++++----- src/tests/user.rs | 63 ++-- src/tests/version.rs | 11 +- src/upload.rs | 58 ++-- src/uploaders.rs | 86 +++-- src/user/middleware.rs | 14 +- src/user/mod.rs | 153 +++++---- src/util/errors.rs | 179 +++++++---- src/util/head.rs | 18 +- src/util/io_util.rs | 14 +- src/util/lazy_cell.rs | 6 +- src/util/mod.rs | 72 +++-- src/util/request_proxy.rs | 20 +- src/version.rs | 214 +++++++------ 43 files changed, 2375 insertions(+), 1740 deletions(-) diff --git a/build.rs b/build.rs index 70c9bb1d8e4..d72b5441d7c 100644 --- a/build.rs +++ b/build.rs @@ -13,8 +13,7 @@ fn main() { if let Ok(database_url) = env::var("TEST_DATABASE_URL") { let connection = PgConnection::establish(&database_url) .expect("Could not connect to TEST_DATABASE_URL"); - run_pending_migrations(&connection) - .expect("Error running migrations"); + run_pending_migrations(&connection).expect("Error running migrations"); } } } diff --git a/src/app.rs b/src/app.rs index b38ee8412a1..acaff6fd17a 100644 --- a/src/app.rs +++ b/src/app.rs @@ -34,17 +34,15 @@ pub struct App { /// The `AppMiddleware` injects an `App` instance into the `Request` extensions pub struct AppMiddleware { - app: Arc + app: Arc, } impl App { pub fn new(config: &Config) -> App { - let mut github = oauth2::Config::new( - &config.gh_client_id, - &config.gh_client_secret, - "https://github.com/login/oauth/authorize", - "https://github.com/login/oauth/access_token", - ); + let mut github = oauth2::Config::new(&config.gh_client_id, + &config.gh_client_secret, + "https://github.com/login/oauth/authorize", + "https://github.com/login/oauth/access_token"); github.scopes.push(String::from("read:org")); @@ -105,13 +103,15 @@ impl AppMiddleware { } impl Middleware for AppMiddleware { - fn before(&self, req: &mut Request) -> Result<(), Box> { + fn before(&self, req: &mut Request) -> Result<(), Box> { req.mut_extensions().insert(self.app.clone()); Ok(()) } - fn after(&self, req: &mut Request, res: Result>) - -> Result> { + fn after(&self, + req: &mut Request, + res: Result>) + -> Result> { req.mut_extensions().pop::>().unwrap(); res } @@ -124,7 +124,6 @@ pub trait RequestApp { impl RequestApp for T { fn app(&self) -> &Arc { - self.extensions().find::>() - .expect("Missing app") + self.extensions().find::>().expect("Missing app") } } diff --git a/src/badge.rs b/src/badge.rs index bcb627b32ed..82bc0f64923 100644 --- a/src/badge.rs +++ b/src/badge.rs @@ -12,31 +12,35 @@ use std::collections::HashMap; pub enum Badge { #[serde(rename = "travis-ci")] TravisCi { - repository: String, branch: Option, + repository: String, + branch: Option, }, #[serde(rename = "appveyor")] Appveyor { - repository: String, branch: Option, service: Option, + repository: String, + branch: Option, + service: Option, }, #[serde(rename = "gitlab")] GitLab { - repository: String, branch: Option, - }, - #[serde(rename = "is-it-maintained-issue-resolution")] - IsItMaintainedIssueResolution { repository: String, + branch: Option, }, + #[serde(rename = "is-it-maintained-issue-resolution")] + IsItMaintainedIssueResolution { repository: String }, #[serde(rename = "is-it-maintained-open-issues")] - IsItMaintainedOpenIssues { - repository: String, - }, + IsItMaintainedOpenIssues { repository: String }, #[serde(rename = "codecov")] Codecov { - repository: String, branch: Option, service: Option, + repository: String, + branch: Option, + service: Option, }, #[serde(rename = "coveralls")] Coveralls { - repository: String, branch: Option, service: Option, + repository: String, + branch: Option, + service: Option, }, } @@ -51,8 +55,7 @@ impl Queryable for Badge { fn build((_, badge_type, attributes): Self::Row) -> Self { let json = json!({"badge_type": badge_type, "attributes": attributes}); - serde_json::from_value(json) - .expect("Invalid CI badge in the database") + serde_json::from_value(json).expect("Invalid CI badge in the database") } } @@ -63,13 +66,13 @@ impl Badge { pub fn badge_type(&self) -> &'static str { match *self { - Badge::TravisCi {..} => "travis-ci", - Badge::Appveyor {..} => "appveyor", - Badge::GitLab{..} => "gitlab", - Badge::IsItMaintainedIssueResolution{..} => "is-it-maintained-issue-resolution", - Badge::IsItMaintainedOpenIssues{..} => "is-it-maintained-open-issues", - Badge::Codecov{..} => "codecov", - Badge::Coveralls{..} => "coveralls", + Badge::TravisCi { .. } => "travis-ci", + Badge::Appveyor { .. } => "appveyor", + Badge::GitLab { .. } => "gitlab", + Badge::IsItMaintainedIssueResolution { .. } => "is-it-maintained-issue-resolution", + Badge::IsItMaintainedOpenIssues { .. } => "is-it-maintained-open-issues", + Badge::Codecov { .. } => "codecov", + Badge::Coveralls { .. } => "coveralls", } } @@ -97,10 +100,10 @@ impl Badge { let json = json!({"badge_type": k, "attributes": attributes_json}); if serde_json::from_value::(json).is_ok() { new_badges.push(NewBadge { - crate_id: krate.id, - badge_type: &**k, - attributes: attributes_json, - }); + crate_id: krate.id, + badge_type: &**k, + attributes: attributes_json, + }); } else { invalid_badges.push(&**k); } @@ -108,9 +111,10 @@ impl Badge { } conn.transaction(|| { - delete(badges::table.filter(badges::crate_id.eq(krate.id))).execute(conn)?; - insert(&new_badges).into(badges::table).execute(conn)?; - Ok(invalid_badges) - }) + delete(badges::table.filter(badges::crate_id.eq(krate.id))) + .execute(conn)?; + insert(&new_badges).into(badges::table).execute(conn)?; + Ok(invalid_badges) + }) } } diff --git a/src/bin/delete-crate.rs b/src/bin/delete-crate.rs index 3c15bc99204..996bac59c7d 100644 --- a/src/bin/delete-crate.rs +++ b/src/bin/delete-crate.rs @@ -30,80 +30,96 @@ fn main() { fn delete(tx: &postgres::transaction::Transaction) { let name = match env::args().nth(1) { - None => { println!("needs a crate-name argument"); return } + None => { + println!("needs a crate-name argument"); + return; + } Some(s) => s, }; let krate = Crate::find_by_name(tx, &name).unwrap(); - print!("Are you sure you want to delete {} ({}) [y/N]: ", name, krate.id); + print!("Are you sure you want to delete {} ({}) [y/N]: ", + name, + krate.id); io::stdout().flush().unwrap(); let mut line = String::new(); io::stdin().read_line(&mut line).unwrap(); - if !line.starts_with("y") { return } + if !line.starts_with("y") { + return; + } let versions = krate.versions(tx).unwrap(); for v in versions.iter() { println!("deleting version {} ({})", v.num, v.id); let n = tx.execute("DELETE FROM version_downloads WHERE version_id = $1", - &[&v.id]).unwrap(); + &[&v.id]) + .unwrap(); println!(" {} download records deleted", n); let n = tx.execute("DELETE FROM version_authors WHERE version_id = $1", - &[&v.id]).unwrap(); + &[&v.id]) + .unwrap(); println!(" {} author records deleted", n); - let n = tx.execute("DELETE FROM dependencies WHERE version_id = $1", - &[&v.id]).unwrap(); + let n = tx.execute("DELETE FROM dependencies WHERE version_id = $1", &[&v.id]) + .unwrap(); println!(" {} dependencies deleted", n); - tx.execute("DELETE FROM versions WHERE id = $1", - &[&v.id]).unwrap(); + tx.execute("DELETE FROM versions WHERE id = $1", &[&v.id]) + .unwrap(); } println!("deleting follows"); - let n = tx.execute("DELETE FROM follows WHERE crate_id = $1", - &[&krate.id]).unwrap(); + let n = tx.execute("DELETE FROM follows WHERE crate_id = $1", &[&krate.id]) + .unwrap(); println!(" {} deleted", n); println!("deleting crate download records"); let n = tx.execute("DELETE FROM crate_downloads WHERE crate_id = $1", - &[&krate.id]).unwrap(); + &[&krate.id]) + .unwrap(); println!(" {} deleted", n); println!("deleting crate owners"); - let n = tx.execute("DELETE FROM crate_owners WHERE crate_id = $1", - &[&krate.id]).unwrap(); + let n = tx.execute("DELETE FROM crate_owners WHERE crate_id = $1", &[&krate.id]) + .unwrap(); println!(" {} deleted", n); println!("disabling reserved crate name trigger"); let _ = tx.execute("ALTER TABLE crates DISABLE TRIGGER trigger_ensure_crate_name_not_reserved;", - &[]).unwrap(); + &[]) + .unwrap(); println!("deleting crate keyword connections"); let n = tx.execute("DELETE FROM crates_keywords WHERE crate_id = $1", - &[&krate.id]).unwrap(); + &[&krate.id]) + .unwrap(); println!(" {} deleted", n); println!("deleting crate category connections"); let n = tx.execute("DELETE FROM crates_categories WHERE crate_id = $1", - &[&krate.id]).unwrap(); + &[&krate.id]) + .unwrap(); println!(" {} deleted", n); println!("enabling reserved crate name trigger"); let _ = tx.execute("ALTER TABLE crates ENABLE TRIGGER trigger_ensure_crate_name_not_reserved;", - &[]).unwrap(); + &[]) + .unwrap(); println!("deleting crate badges"); - let n = tx.execute("DELETE FROM badges WHERE crate_id = $1", - &[&krate.id]).unwrap(); + let n = tx.execute("DELETE FROM badges WHERE crate_id = $1", &[&krate.id]) + .unwrap(); println!(" {} deleted", n); println!("deleting the crate"); - let n = tx.execute("DELETE FROM crates WHERE id = $1", - &[&krate.id]).unwrap(); + let n = tx.execute("DELETE FROM crates WHERE id = $1", &[&krate.id]) + .unwrap(); println!(" {} deleted", n); print!("commit? [y/N]: "); io::stdout().flush().unwrap(); let mut line = String::new(); io::stdin().read_line(&mut line).unwrap(); - if !line.starts_with("y") { panic!("aborting transaction"); } + if !line.starts_with("y") { + panic!("aborting transaction"); + } } diff --git a/src/bin/delete-version.rs b/src/bin/delete-version.rs index c3711175146..55c5b02d75c 100644 --- a/src/bin/delete-version.rs +++ b/src/bin/delete-version.rs @@ -31,40 +31,56 @@ fn main() { fn delete(tx: &postgres::transaction::Transaction) { let name = match env::args().nth(1) { - None => { println!("needs a crate-name argument"); return } + None => { + println!("needs a crate-name argument"); + return; + } Some(s) => s, }; let version = match env::args().nth(2) { - None => { println!("needs a version argument"); return } + None => { + println!("needs a version argument"); + return; + } Some(s) => s, }; let version = semver::Version::parse(&version).unwrap(); let krate = Crate::find_by_name(tx, &name).unwrap(); - let v = Version::find_by_num(tx, krate.id, &version).unwrap().unwrap(); - print!("Are you sure you want to delete {}#{} ({}) [y/N]: ", name, version, + let v = Version::find_by_num(tx, krate.id, &version) + .unwrap() + .unwrap(); + print!("Are you sure you want to delete {}#{} ({}) [y/N]: ", + name, + version, v.id); io::stdout().flush().unwrap(); let mut line = String::new(); io::stdin().read_line(&mut line).unwrap(); - if !line.starts_with("y") { return } + if !line.starts_with("y") { + return; + } println!("deleting version {} ({})", v.num, v.id); let n = tx.execute("DELETE FROM version_downloads WHERE version_id = $1", - &[&v.id]).unwrap(); + &[&v.id]) + .unwrap(); println!(" {} download records deleted", n); let n = tx.execute("DELETE FROM version_authors WHERE version_id = $1", - &[&v.id]).unwrap(); + &[&v.id]) + .unwrap(); println!(" {} author records deleted", n); - let n = tx.execute("DELETE FROM dependencies WHERE version_id = $1", - &[&v.id]).unwrap(); + let n = tx.execute("DELETE FROM dependencies WHERE version_id = $1", &[&v.id]) + .unwrap(); println!(" {} dependencies deleted", n); - tx.execute("DELETE FROM versions WHERE id = $1", - &[&v.id]).unwrap(); + tx.execute("DELETE FROM versions WHERE id = $1", &[&v.id]) + .unwrap(); print!("commit? [y/N]: "); io::stdout().flush().unwrap(); let mut line = String::new(); io::stdin().read_line(&mut line).unwrap(); - if !line.starts_with("y") { panic!("aborting transaction"); } + if !line.starts_with("y") { + panic!("aborting transaction"); + } } diff --git a/src/bin/fill-in-user-id.rs b/src/bin/fill-in-user-id.rs index e1dfae7442d..1fa69ad6961 100644 --- a/src/bin/fill-in-user-id.rs +++ b/src/bin/fill-in-user-id.rs @@ -53,13 +53,17 @@ struct GithubUser { fn update(app: &App, tx: &postgres::transaction::Transaction) { let query = "SELECT id, gh_login, gh_access_token, gh_avatar FROM users WHERE gh_id IS NULL"; - let rows = tx.query(query, &[]).unwrap().into_iter().map(|row| { - let id: i32 = row.get("id"); - let login: String = row.get("gh_login"); - let token: String = row.get("gh_access_token"); - let avatar: Option = row.get("gh_avatar"); - (id, login, http::token(token), avatar) - }).collect::>(); + let rows = tx.query(query, &[]) + .unwrap() + .into_iter() + .map(|row| { + let id: i32 = row.get("id"); + let login: String = row.get("gh_login"); + let token: String = row.get("gh_access_token"); + let avatar: Option = row.get("gh_avatar"); + (id, login, http::token(token), avatar) + }) + .collect::>(); for (id, login, token, avatar) in rows { println!("attempt: {}/{}", id, login); @@ -69,12 +73,12 @@ fn update(app: &App, tx: &postgres::transaction::Transaction) { let ghuser: GithubUser = http::parse_github_response(handle, &resp)?; if let Some(ref avatar) = avatar { if !avatar.contains(&ghuser.id.to_string()) { - return Err(human(&format_args!("avatar: {}", avatar))) + return Err(human(&format_args!("avatar: {}", avatar))); } } if ghuser.login == login { tx.execute("UPDATE users SET gh_id = $1 WHERE id = $2", - &[&ghuser.id, &id])?; + &[&ghuser.id, &id])?; Ok(()) } else { Err(human(&format_args!("different login: {}", ghuser.login))) @@ -85,4 +89,3 @@ fn update(app: &App, tx: &postgres::transaction::Transaction) { } } } - diff --git a/src/bin/populate.rs b/src/bin/populate.rs index b4567d6c367..29ba6caf18a 100644 --- a/src/bin/populate.rs +++ b/src/bin/populate.rs @@ -27,9 +27,9 @@ fn main() { } fn update(tx: &postgres::transaction::Transaction) -> postgres::Result<()> { - let ids = env::args().skip(1).filter_map(|arg| { - arg.parse::().ok() - }); + let ids = env::args() + .skip(1) + .filter_map(|arg| arg.parse::().ok()); for id in ids { let now = time::now_utc().to_timespec(); let mut rng = StdRng::new().unwrap(); @@ -41,7 +41,7 @@ fn update(tx: &postgres::transaction::Transaction) -> postgres::Result<()> { tx.execute("INSERT INTO version_downloads \ (version_id, downloads, date) \ VALUES ($1, $2, $3)", - &[&id, &dls, &moment])?; + &[&id, &dls, &moment])?; } } Ok(()) diff --git a/src/bin/server.rs b/src/bin/server.rs index daadf46a9f7..7109339b5d3 100644 --- a/src/bin/server.rs +++ b/src/bin/server.rs @@ -31,8 +31,9 @@ fn main() { let mut opts = git2::FetchOptions::new(); opts.remote_callbacks(cb); git2::build::RepoBuilder::new() - .fetch_options(opts) - .clone(&url, &checkout).unwrap() + .fetch_options(opts) + .clone(&url, &checkout) + .unwrap() } }; let mut cfg = repo.config().unwrap(); @@ -64,7 +65,7 @@ fn main() { &api_protocol), proxy: None, } - }, + } (Env::Production, Replica::ReadOnlyMirror) => { // Read-only mirrors don't need access key or secret key, // but they might have them. Definitely need bucket though. @@ -76,7 +77,7 @@ fn main() { &api_protocol), proxy: None, } - }, + } _ => { if env::var("S3_BUCKET").is_ok() { println!("Using S3 uploader"); @@ -92,7 +93,7 @@ fn main() { println!("Using local uploader, crate files will be in the dist directory"); Uploader::Local } - }, + } }; let config = cargo_registry::Config { @@ -115,9 +116,12 @@ fn main() { let port = if heroku { 8888 } else { - env::var("PORT").ok().and_then(|s| s.parse().ok()).unwrap_or(8888) + env::var("PORT") + .ok() + .and_then(|s| s.parse().ok()) + .unwrap_or(8888) }; - let threads = if cargo_env == Env::Development {1} else {50}; + let threads = if cargo_env == Env::Development { 1 } else { 50 }; let mut cfg = civet::Config::new(); cfg.port(port).threads(threads).keep_alive(true); let _a = Server::start(cfg, app); diff --git a/src/bin/transfer-crates.rs b/src/bin/transfer-crates.rs index 817a1943d3f..01539b4fc98 100644 --- a/src/bin/transfer-crates.rs +++ b/src/bin/transfer-crates.rs @@ -31,11 +31,17 @@ fn main() { fn transfer(tx: &postgres::transaction::Transaction) { let from = match env::args().nth(1) { - None => { println!("needs a from-user argument"); return } + None => { + println!("needs a from-user argument"); + return; + } Some(s) => s, }; let to = match env::args().nth(2) { - None => { println!("needs a to-user argument"); return } + None => { + println!("needs a to-user argument"); + return; + } Some(s) => s, }; @@ -55,14 +61,15 @@ fn transfer(tx: &postgres::transaction::Transaction) { } println!("Are you sure you want to transfer crates from {} to {}", - from.gh_login, to.gh_login); + from.gh_login, + to.gh_login); get_confirm("continue"); let stmt = tx.prepare("SELECT * FROM crate_owners WHERE owner_id = $1 AND owner_kind = $2") - .unwrap(); + .unwrap(); let rows = stmt.query(&[&from.id, &(OwnerKind::User as i32)]).unwrap(); for row in rows.iter() { let id: i32 = row.get("id"); @@ -74,7 +81,8 @@ fn transfer(tx: &postgres::transaction::Transaction) { } let n = tx.execute("UPDATE crate_owners SET owner_id = $1 WHERE id $2", - &[&to.id, &id]).unwrap(); + &[&to.id, &id]) + .unwrap(); assert_eq!(n, 1); } diff --git a/src/bin/update-downloads.rs b/src/bin/update-downloads.rs index 299d97558aa..4aaa25bc0d4 100644 --- a/src/bin/update-downloads.rs +++ b/src/bin/update-downloads.rs @@ -17,8 +17,7 @@ static LIMIT: i64 = 1000; #[allow(dead_code)] // dead in tests fn main() { - let daemon = env::args().nth(1).as_ref().map(|s| &s[..]) - == Some("daemon"); + let daemon = env::args().nth(1).as_ref().map(|s| &s[..]) == Some("daemon"); let sleep = env::args().nth(2).map(|s| s.parse().unwrap()); loop { let conn = cargo_registry::db::connect_now(); @@ -27,7 +26,7 @@ fn main() { if daemon { std::thread::sleep(Duration::new(sleep.unwrap(), 0)); } else { - break + break; } } } @@ -37,7 +36,8 @@ fn update(conn: &postgres::GenericConnection) -> postgres::Result<()> { loop { // FIXME(rust-lang/rust#27401): weird declaration to make sure this // variable gets dropped. - let tx; tx = conn.transaction()?; + let tx; + tx = conn.transaction()?; { let stmt = tx.prepare("SELECT * FROM version_downloads \ WHERE processed = FALSE AND id > $1 @@ -56,7 +56,8 @@ fn update(conn: &postgres::GenericConnection) -> postgres::Result<()> { } fn collect(tx: &postgres::transaction::Transaction, - rows: &mut postgres::rows::Rows) -> postgres::Result> { + rows: &mut postgres::rows::Rows) + -> postgres::Result> { // Anything older than 24 hours ago will be frozen and will not be queried // against again. let now = chrono::UTC::now(); @@ -67,9 +68,11 @@ fn collect(tx: &postgres::transaction::Transaction, let download: VersionDownload = Model::from_row(&row); assert!(map.insert(download.id, download).is_none()); } - println!("updating {} versions (cutoff {})", map.len(), now.to_rfc2822()); + println!("updating {} versions (cutoff {})", + map.len(), + now.to_rfc2822()); if map.len() == 0 { - return Ok(None) + return Ok(None); } let mut max = 0; @@ -79,7 +82,7 @@ fn collect(tx: &postgres::transaction::Transaction, max = *id; } if download.date > cutoff && download.counted == download.downloads { - continue + continue; } let amt = download.downloads - download.counted; @@ -88,11 +91,11 @@ fn collect(tx: &postgres::transaction::Transaction, tx.execute("UPDATE version_downloads SET processed = $2, counted = counted + $3 WHERE id = $1", - &[id, &(download.date < cutoff), &amt])?; + &[id, &(download.date < cutoff), &amt])?; total += amt as i64; if amt == 0 { - continue + continue; } let crate_id = Version::find(tx, download.version_id).unwrap().crate_id; @@ -101,10 +104,11 @@ fn collect(tx: &postgres::transaction::Transaction, tx.execute("UPDATE versions SET downloads = downloads + $1 WHERE id = $2", - &[&amt, &download.version_id])?; + &[&amt, &download.version_id])?; // Update the total number of crate downloads tx.execute("UPDATE crates SET downloads = downloads + $1 - WHERE id = $2", &[&amt, &crate_id])?; + WHERE id = $2", + &[&amt, &crate_id])?; // Update the total number of crate downloads for today let cnt = tx.execute("UPDATE crate_downloads @@ -115,14 +119,14 @@ fn collect(tx: &postgres::transaction::Transaction, tx.execute("INSERT INTO crate_downloads (crate_id, downloads, date) VALUES ($1, $2, $3)", - &[&crate_id, &amt, &download.date])?; + &[&crate_id, &amt, &download.date])?; } } // After everything else is done, update the global counter of total // downloads. tx.execute("UPDATE metadata SET total_downloads = total_downloads + $1", - &[&total])?; + &[&total])?; Ok(Some(max)) } @@ -140,20 +144,24 @@ mod test { use cargo_registry::{Version, Crate, User, Model, env}; fn conn() -> postgres::Connection { - postgres::Connection::connect(&env("TEST_DATABASE_URL")[..], - postgres::TlsMode::None).unwrap() + postgres::Connection::connect(&env("TEST_DATABASE_URL")[..], postgres::TlsMode::None) + .unwrap() } - fn user(conn: &postgres::transaction::Transaction) -> User{ - User::find_or_insert(conn, 2, "login", None, None, None, - "access_token").unwrap() + fn user(conn: &postgres::transaction::Transaction) -> User { + User::find_or_insert(conn, 2, "login", None, None, None, "access_token").unwrap() } fn crate_downloads(tx: &postgres::transaction::Transaction, id: i32, expected: usize) { let stmt = tx.prepare("SELECT * FROM crate_downloads - WHERE crate_id = $1").unwrap(); - let dl: i32 = stmt.query(&[&id]).unwrap().iter() - .next().unwrap().get("downloads"); + WHERE crate_id = $1") + .unwrap(); + let dl: i32 = stmt.query(&[&id]) + .unwrap() + .iter() + .next() + .unwrap() + .get("downloads"); assert_eq!(dl, expected as i32); } @@ -162,20 +170,34 @@ mod test { let conn = conn(); let tx = conn.transaction().unwrap(); let user = user(&tx); - let krate = Crate::find_or_insert(&tx, "foo", user.id, &None, &None, - &None, &None, &None, &None, - &None, None).unwrap(); - let version = Version::insert(&tx, krate.id, + let krate = Crate::find_or_insert(&tx, + "foo", + user.id, + &None, + &None, + &None, + &None, + &None, + &None, + &None, + None) + .unwrap(); + let version = Version::insert(&tx, + krate.id, &semver::Version::parse("1.0.0").unwrap(), - &HashMap::new(), &[]).unwrap(); + &HashMap::new(), + &[]) + .unwrap(); tx.execute("INSERT INTO version_downloads \ (version_id) VALUES ($1)", - &[&version.id]).unwrap(); + &[&version.id]) + .unwrap(); tx.execute("INSERT INTO version_downloads \ (version_id, date, processed) VALUES ($1, current_date - interval '1 day', true)", - &[&version.id]).unwrap(); + &[&version.id]) + .unwrap(); ::update(&tx).unwrap(); assert_eq!(Version::find(&tx, version.id).unwrap().downloads, 1); assert_eq!(Crate::find(&tx, krate.id).unwrap().downloads, 1); @@ -189,21 +211,39 @@ mod test { let conn = conn(); let tx = conn.transaction().unwrap(); let user = user(&tx); - let krate = Crate::find_or_insert(&tx, "foo", user.id, &None, - &None, &None, &None, &None, - &None, &None, None).unwrap(); - let version = Version::insert(&tx, krate.id, + let krate = Crate::find_or_insert(&tx, + "foo", + user.id, + &None, + &None, + &None, + &None, + &None, + &None, + &None, + None) + .unwrap(); + let version = Version::insert(&tx, + krate.id, &semver::Version::parse("1.0.0").unwrap(), - &HashMap::new(), &[]).unwrap(); + &HashMap::new(), + &[]) + .unwrap(); tx.execute("INSERT INTO version_downloads \ (version_id, downloads, counted, date, processed) VALUES ($1, 2, 2, current_date - interval '2 days', false)", - &[&version.id]).unwrap(); + &[&version.id]) + .unwrap(); ::update(&tx).unwrap(); let stmt = tx.prepare("SELECT processed FROM version_downloads - WHERE version_id = $1").unwrap(); - let processed: bool = stmt.query(&[&version.id]).unwrap().iter() - .next().unwrap().get("processed"); + WHERE version_id = $1") + .unwrap(); + let processed: bool = stmt.query(&[&version.id]) + .unwrap() + .iter() + .next() + .unwrap() + .get("processed"); assert!(processed); } @@ -212,22 +252,40 @@ mod test { let conn = conn(); let tx = conn.transaction().unwrap(); let user = user(&tx); - let krate = Crate::find_or_insert(&tx, "foo", user.id, &None, - &None, &None, &None, &None, - &None, &None, None).unwrap(); - let version = Version::insert(&tx, krate.id, + let krate = Crate::find_or_insert(&tx, + "foo", + user.id, + &None, + &None, + &None, + &None, + &None, + &None, + &None, + None) + .unwrap(); + let version = Version::insert(&tx, + krate.id, &semver::Version::parse("1.0.0").unwrap(), - &HashMap::new(), &[]).unwrap(); + &HashMap::new(), + &[]) + .unwrap(); let time = time::now_utc().to_timespec() - Duration::hours(2); tx.execute("INSERT INTO version_downloads \ (version_id, downloads, counted, date, processed) VALUES ($1, 2, 2, date($2), false)", - &[&version.id, &time]).unwrap(); + &[&version.id, &time]) + .unwrap(); ::update(&tx).unwrap(); let stmt = tx.prepare("SELECT processed FROM version_downloads - WHERE version_id = $1").unwrap(); - let processed: bool = stmt.query(&[&version.id]).unwrap().iter() - .next().unwrap().get("processed"); + WHERE version_id = $1") + .unwrap(); + let processed: bool = stmt.query(&[&version.id]) + .unwrap() + .iter() + .next() + .unwrap() + .get("processed"); assert!(!processed); } @@ -236,26 +294,42 @@ mod test { let conn = conn(); let tx = conn.transaction().unwrap(); let user = user(&tx); - let krate = Crate::find_or_insert(&tx, "foo", user.id, &None, - &None, &None, &None, &None, - &None, &None, None).unwrap(); - let version = Version::insert(&tx, krate.id, + let krate = Crate::find_or_insert(&tx, + "foo", + user.id, + &None, + &None, + &None, + &None, + &None, + &None, + &None, + None) + .unwrap(); + let version = Version::insert(&tx, + krate.id, &semver::Version::parse("1.0.0").unwrap(), - &HashMap::new(), &[]).unwrap(); + &HashMap::new(), + &[]) + .unwrap(); tx.execute("UPDATE versions SET updated_at = current_date - interval '2 hours'", - &[]).unwrap(); + &[]) + .unwrap(); tx.execute("UPDATE crates SET updated_at = current_date - interval '2 hours'", - &[]).unwrap(); + &[]) + .unwrap(); tx.execute("INSERT INTO version_downloads \ (version_id, downloads, counted, date, processed) VALUES ($1, 2, 1, current_date, false)", - &[&version.id]).unwrap(); + &[&version.id]) + .unwrap(); tx.execute("INSERT INTO version_downloads \ (version_id, date) VALUES ($1, current_date - interval '1 day')", - &[&version.id]).unwrap(); + &[&version.id]) + .unwrap(); let version_before = Version::find(&tx, version.id).unwrap(); let krate_before = Crate::find(&tx, krate.id).unwrap(); @@ -276,22 +350,37 @@ mod test { let conn = conn(); let tx = conn.transaction().unwrap(); let user = user(&tx); - let krate = Crate::find_or_insert(&tx, "foo", user.id, &None, - &None, &None, &None, &None, - &None, &None, None).unwrap(); - let version = Version::insert(&tx, krate.id, + let krate = Crate::find_or_insert(&tx, + "foo", + user.id, + &None, + &None, + &None, + &None, + &None, + &None, + &None, + None) + .unwrap(); + let version = Version::insert(&tx, + krate.id, &semver::Version::parse("1.0.0").unwrap(), - &HashMap::new(), &[]).unwrap(); + &HashMap::new(), + &[]) + .unwrap(); tx.execute("UPDATE versions SET updated_at = current_date - interval '2 days'", - &[]).unwrap(); + &[]) + .unwrap(); tx.execute("UPDATE crates SET updated_at = current_date - interval '2 days'", - &[]).unwrap(); + &[]) + .unwrap(); tx.execute("INSERT INTO version_downloads \ (version_id, downloads, counted, date, processed) VALUES ($1, 2, 2, current_date - interval '2 days', false)", - &[&version.id]).unwrap(); + &[&version.id]) + .unwrap(); let version_before = Version::find(&tx, version.id).unwrap(); let krate_before = Crate::find(&tx, krate.id).unwrap(); diff --git a/src/categories.rs b/src/categories.rs index 6cb41b05669..c927351367c 100644 --- a/src/categories.rs +++ b/src/categories.rs @@ -13,7 +13,10 @@ struct Category { } impl Category { - fn from_parent(slug: &str, name: &str, description: &str, parent: Option<&Category>) + fn from_parent(slug: &str, + name: &str, + description: &str, + parent: Option<&Category>) -> Category { match parent { Some(parent) => { @@ -43,34 +46,33 @@ fn required_string_from_toml<'a>(toml: &'a toml::Table, key: &str) -> CargoResul } fn optional_string_from_toml<'a>(toml: &'a toml::Table, key: &str) -> &'a str { - toml.get(key) - .and_then(toml::Value::as_str) - .unwrap_or("") + toml.get(key).and_then(toml::Value::as_str).unwrap_or("") } -fn categories_from_toml(categories: &toml::Table, parent: Option<&Category>) -> CargoResult> { +fn categories_from_toml(categories: &toml::Table, + parent: Option<&Category>) + -> CargoResult> { let mut result = vec![]; for (slug, details) in categories { - let details = details.as_table().chain_error(|| { - internal(&format_args!("category {} was not a TOML table", slug)) - })?; + let details = + details + .as_table() + .chain_error(|| internal(&format_args!("category {} was not a TOML table", slug)))?; - let category = Category::from_parent( - slug, - required_string_from_toml(details, "name")?, - optional_string_from_toml(details, "description"), - parent, - ); + let category = Category::from_parent(slug, + required_string_from_toml(details, "name")?, + optional_string_from_toml(details, "description"), + parent); if let Some(categories) = details.get("categories") { - let categories = categories.as_table().chain_error(|| { - internal(&format_args!("child categories of {} were not a table", slug)) - })?; + let categories = categories + .as_table() + .chain_error(|| { + internal(&format_args!("child categories of {} were not a table", slug)) + })?; - result.extend( - categories_from_toml(categories, Some(&category))? - ); + result.extend(categories_from_toml(categories, Some(&category))?); } result.push(category) @@ -84,13 +86,12 @@ pub fn sync() -> CargoResult<()> { let tx = conn.transaction().unwrap(); let categories = include_str!("./categories.toml"); - let toml = toml::Parser::new(categories).parse().expect( - "Could not parse categories.toml" - ); + let toml = toml::Parser::new(categories) + .parse() + .expect("Could not parse categories.toml"); - let categories = categories_from_toml(&toml, None).expect( - "Could not convert categories from TOML" - ); + let categories = categories_from_toml(&toml, None) + .expect("Could not convert categories from TOML"); for category in &categories { tx.execute("\ @@ -99,20 +100,20 @@ pub fn sync() -> CargoResult<()> { ON CONFLICT (slug) DO UPDATE \ SET category = EXCLUDED.category, \ description = EXCLUDED.description;", - &[&category.slug, &category.name, &category.description] - )?; + &[&category.slug, &category.name, &category.description])?; } - let in_clause = categories.iter().map(|category| { - format!("LOWER('{}')", category.slug) - }).collect::>().join(","); + let in_clause = categories + .iter() + .map(|category| format!("LOWER('{}')", category.slug)) + .collect::>() + .join(","); tx.execute(&format!("\ DELETE FROM categories \ WHERE slug NOT IN ({});", in_clause), - &[] - )?; + &[])?; tx.set_commit(); tx.finish().unwrap(); Ok(()) diff --git a/src/category.rs b/src/category.rs index f6f45cb2188..70f14899523 100644 --- a/src/category.rs +++ b/src/category.rs @@ -57,29 +57,34 @@ pub struct EncodableCategoryWithSubcategories { } impl Category { - pub fn find_by_category(conn: &GenericConnection, name: &str) - -> CargoResult { + pub fn find_by_category(conn: &GenericConnection, name: &str) -> CargoResult { let stmt = conn.prepare("SELECT * FROM categories \ WHERE category = $1")?; let rows = stmt.query(&[&name])?; - rows.iter().next() - .chain_error(|| NotFound) - .map(|row| Model::from_row(&row)) + rows.iter() + .next() + .chain_error(|| NotFound) + .map(|row| Model::from_row(&row)) } - pub fn find_by_slug(conn: &GenericConnection, slug: &str) - -> CargoResult { + pub fn find_by_slug(conn: &GenericConnection, slug: &str) -> CargoResult { let stmt = conn.prepare("SELECT * FROM categories \ WHERE slug = LOWER($1)")?; let rows = stmt.query(&[&slug])?; - rows.iter().next() - .chain_error(|| NotFound) - .map(|row| Model::from_row(&row)) + rows.iter() + .next() + .chain_error(|| NotFound) + .map(|row| Model::from_row(&row)) } pub fn encodable(self) -> EncodableCategory { let Category { - crates_cnt, category, slug, description, created_at, .. + crates_cnt, + category, + slug, + description, + created_at, + .. } = self; EncodableCategory { id: slug.clone(), @@ -93,59 +98,68 @@ impl Category { pub fn update_crate<'a>(conn: &PgConnection, krate: &Crate, - slugs: &[&'a str]) -> QueryResult> { + slugs: &[&'a str]) + -> QueryResult> { use diesel::expression::dsl::any; conn.transaction(|| { let categories = categories::table .filter(categories::slug.eq(any(slugs))) .load::(conn)?; - let invalid_categories = slugs.iter().cloned() + let invalid_categories = slugs + .iter() + .cloned() .filter(|s| !categories.iter().any(|c| c.slug == *s)) .collect(); - let crate_categories = categories.iter() - .map(|c| CrateCategory { category_id: c.id, crate_id: krate.id }) + let crate_categories = categories + .iter() + .map(|c| { + CrateCategory { + category_id: c.id, + crate_id: krate.id, + } + }) .collect::>(); delete(CrateCategory::belonging_to(krate)).execute(conn)?; - insert(&crate_categories).into(crates_categories::table).execute(conn)?; + insert(&crate_categories) + .into(crates_categories::table) + .execute(conn)?; Ok(invalid_categories) }) } pub fn update_crate_old(conn: &GenericConnection, - krate: &Crate, - categories: &[String]) -> CargoResult> { + krate: &Crate, + categories: &[String]) + -> CargoResult> { let old_categories = krate.categories(conn)?; - let old_categories_ids: HashSet<_> = old_categories.iter().map(|cat| { - cat.id - }).collect(); + let old_categories_ids: HashSet<_> = old_categories.iter().map(|cat| cat.id).collect(); // If a new category specified is not in the database, filter // it out and don't add it. Return it to be able to warn about it. let mut invalid_categories = vec![]; - let new_categories: Vec = categories.iter().flat_map(|c| { - match Category::find_by_slug(conn, c) { - Ok(cat) => Some(cat), - Err(_) => { - invalid_categories.push(c.to_string()); - None - }, - } - }).collect(); - - let new_categories_ids: HashSet<_> = new_categories.iter().map(|cat| { - cat.id - }).collect(); + let new_categories: Vec = categories + .iter() + .flat_map(|c| match Category::find_by_slug(conn, c) { + Ok(cat) => Some(cat), + Err(_) => { + invalid_categories.push(c.to_string()); + None + } + }) + .collect(); + + let new_categories_ids: HashSet<_> = new_categories.iter().map(|cat| cat.id).collect(); let to_rm: Vec<_> = old_categories_ids - .difference(&new_categories_ids) - .cloned() - .collect(); + .difference(&new_categories_ids) + .cloned() + .collect(); let to_add: Vec<_> = new_categories_ids - .difference(&old_categories_ids) - .cloned() - .collect(); + .difference(&old_categories_ids) + .cloned() + .collect(); if !to_rm.is_empty() { conn.execute("DELETE FROM crates_categories \ @@ -155,9 +169,10 @@ impl Category { } if !to_add.is_empty() { - let insert: Vec<_> = to_add.into_iter().map(|id| { - format!("({}, {})", krate.id, id) - }).collect(); + let insert: Vec<_> = to_add + .into_iter() + .map(|id| format!("({}, {})", krate.id, id)) + .collect(); let insert = insert.join(", "); conn.execute(&format!("INSERT INTO crates_categories \ (crate_id, category_id) VALUES {}", @@ -183,7 +198,8 @@ impl Category { pub fn toplevel(conn: &PgConnection, sort: &str, limit: i64, - offset: i64) -> QueryResult> { + offset: i64) + -> QueryResult> { use diesel::select; use diesel::expression::dsl::*; @@ -203,13 +219,15 @@ impl Category { GROUP BY c.id {} LIMIT {} OFFSET {}", sort_sql, limit, offset - ))).load(conn) + ))) + .load(conn) } pub fn toplevel_old(conn: &GenericConnection, - sort: &str, - limit: i64, - offset: i64) -> CargoResult> { + sort: &str, + limit: i64, + offset: i64) + -> CargoResult> { let sort_sql = match sort { "crates" => "ORDER BY crates_cnt DESC", @@ -237,8 +255,7 @@ impl Category { Ok(categories) } - pub fn subcategories(&self, conn: &GenericConnection) - -> CargoResult> { + pub fn subcategories(&self, conn: &GenericConnection) -> CargoResult> { let stmt = conn.prepare("\ SELECT c.id, c.category, c.slug, c.description, c.created_at, \ COALESCE (( \ @@ -277,8 +294,7 @@ impl<'a> NewCategory<'a> { return Ok(c); } - categories.filter(slug.eq(self.slug)) - .first(conn) + categories.filter(slug.eq(self.slug)).first(conn) } } @@ -293,7 +309,9 @@ impl Model for Category { description: row.get("description"), } } - fn table_name(_: Option) -> &'static str { "categories" } + fn table_name(_: Option) -> &'static str { + "categories" + } } /// Handles the `GET /categories` route. @@ -310,14 +328,19 @@ pub fn index(req: &mut Request) -> CargoResult { let total = Category::count_toplevel(conn)?; #[derive(RustcEncodable)] - struct R { categories: Vec, meta: Meta } + struct R { + categories: Vec, + meta: Meta, + } #[derive(RustcEncodable)] - struct Meta { total: i64 } + struct Meta { + total: i64, + } Ok(req.json(&R { - categories: categories, - meta: Meta { total: total }, - })) + categories: categories, + meta: Meta { total: total }, + })) } /// Handles the `GET /categories/:category_id` route. @@ -325,9 +348,10 @@ pub fn show(req: &mut Request) -> CargoResult { let slug = &req.params()["category_id"]; let conn = req.tx()?; let cat = Category::find_by_slug(conn, slug)?; - let subcats = cat.subcategories(conn)?.into_iter().map(|s| { - s.encodable() - }).collect(); + let subcats = cat.subcategories(conn)? + .into_iter() + .map(|s| s.encodable()) + .collect(); let cat = cat.encodable(); let cat_with_subcats = EncodableCategoryWithSubcategories { id: cat.id, @@ -340,7 +364,9 @@ pub fn show(req: &mut Request) -> CargoResult { }; #[derive(RustcEncodable)] - struct R { category: EncodableCategoryWithSubcategories} + struct R { + category: EncodableCategoryWithSubcategories, + } Ok(req.json(&R { category: cat_with_subcats })) } @@ -352,15 +378,25 @@ pub fn slugs(req: &mut Request) -> CargoResult { let rows = stmt.query(&[])?; #[derive(RustcEncodable)] - struct Slug { id: String, slug: String } + struct Slug { + id: String, + slug: String, + } - let slugs: Vec = rows.iter().map(|r| { - let slug: String = r.get("slug"); - Slug { id: slug.clone(), slug: slug } - }).collect(); + let slugs: Vec = rows.iter() + .map(|r| { + let slug: String = r.get("slug"); + Slug { + id: slug.clone(), + slug: slug, + } + }) + .collect(); #[derive(RustcEncodable)] - struct R { category_slugs: Vec } + struct R { + category_slugs: Vec, + } Ok(req.json(&R { category_slugs: slugs })) } @@ -377,7 +413,8 @@ mod tests { .expect("TEST_DATABASE_URL must be set to run tests"); let conn = PgConnection::establish(&database_url).unwrap(); // These tests deadlock if run concurrently - conn.batch_execute("BEGIN; LOCK categories IN ACCESS EXCLUSIVE MODE").unwrap(); + conn.batch_execute("BEGIN; LOCK categories IN ACCESS EXCLUSIVE MODE") + .unwrap(); conn } @@ -386,10 +423,14 @@ mod tests { let conn = pg_connection(); conn.batch_execute("INSERT INTO categories (category, slug) VALUES ('Cat 2', 'cat2'), ('Cat 1', 'cat1'), ('Cat 1::sub', 'cat1::sub') - ").unwrap(); - - let categories = Category::toplevel(&conn, "", 10, 0).unwrap() - .into_iter().map(|c| c.category).collect::>(); + ") + .unwrap(); + + let categories = Category::toplevel(&conn, "", 10, 0) + .unwrap() + .into_iter() + .map(|c| c.category) + .collect::>(); let expected = vec!["Cat 1".to_string(), "Cat 2".to_string()]; assert_eq!(expected, categories); } @@ -399,10 +440,14 @@ mod tests { let conn = pg_connection(); conn.batch_execute("INSERT INTO categories (category, slug, crates_cnt) VALUES ('Cat 1', 'cat1', 0), ('Cat 2', 'cat2', 2), ('Cat 3', 'cat3', 1) - ").unwrap(); - - let categories = Category::toplevel(&conn, "crates", 10, 0).unwrap() - .into_iter().map(|c| c.category).collect::>(); + ") + .unwrap(); + + let categories = Category::toplevel(&conn, "crates", 10, 0) + .unwrap() + .into_iter() + .map(|c| c.category) + .collect::>(); let expected = vec!["Cat 2".to_string(), "Cat 3".to_string(), "Cat 1".to_string()]; assert_eq!(expected, categories); } @@ -412,15 +457,22 @@ mod tests { let conn = pg_connection(); conn.batch_execute("INSERT INTO categories (category, slug) VALUES ('Cat 1', 'cat1'), ('Cat 2', 'cat2') - ").unwrap(); - - let categories = Category::toplevel(&conn, "", 1, 0).unwrap() - .into_iter().map(|c| c.category).collect::>(); + ") + .unwrap(); + + let categories = Category::toplevel(&conn, "", 1, 0) + .unwrap() + .into_iter() + .map(|c| c.category) + .collect::>(); let expected = vec!["Cat 1".to_string()]; assert_eq!(expected, categories); - let categories = Category::toplevel(&conn, "", 1, 1).unwrap() - .into_iter().map(|c| c.category).collect::>(); + let categories = Category::toplevel(&conn, "", 1, 1) + .unwrap() + .into_iter() + .map(|c| c.category) + .collect::>(); let expected = vec!["Cat 2".to_string()]; assert_eq!(expected, categories); } @@ -432,10 +484,14 @@ mod tests { ('Cat 1', 'cat1', 1), ('Cat 1::sub', 'cat1::sub', 2), ('Cat 2', 'cat2', 3), ('Cat 2::Sub 1', 'cat2::sub1', 4), ('Cat 2::Sub 2', 'cat2::sub2', 5), ('Cat 3', 'cat3', 6) - ").unwrap(); - - let categories = Category::toplevel(&conn, "crates", 10, 0).unwrap() - .into_iter().map(|c| (c.category, c.crates_cnt)).collect::>(); + ") + .unwrap(); + + let categories = Category::toplevel(&conn, "crates", 10, 0) + .unwrap() + .into_iter() + .map(|c| (c.category, c.crates_cnt)) + .collect::>(); let expected = vec![ ("Cat 2".to_string(), 12), ("Cat 3".to_string(), 6), @@ -451,18 +507,25 @@ mod tests { ('Cat 1', 'cat1', 1), ('Cat 1::sub', 'cat1::sub', 2), ('Cat 2', 'cat2', 3), ('Cat 2::Sub 1', 'cat2::sub1', 4), ('Cat 2::Sub 2', 'cat2::sub2', 5), ('Cat 3', 'cat3', 6) - ").unwrap(); - - let categories = Category::toplevel(&conn, "crates", 2, 0).unwrap() - .into_iter().map(|c| (c.category, c.crates_cnt)).collect::>(); + ") + .unwrap(); + + let categories = Category::toplevel(&conn, "crates", 2, 0) + .unwrap() + .into_iter() + .map(|c| (c.category, c.crates_cnt)) + .collect::>(); let expected = vec![ ("Cat 2".to_string(), 12), ("Cat 3".to_string(), 6), ]; assert_eq!(expected, categories); - let categories = Category::toplevel(&conn, "crates", 2, 1).unwrap() - .into_iter().map(|c| (c.category, c.crates_cnt)).collect::>(); + let categories = Category::toplevel(&conn, "crates", 2, 1) + .unwrap() + .into_iter() + .map(|c| (c.category, c.crates_cnt)) + .collect::>(); let expected = vec![ ("Cat 3".to_string(), 6), ("Cat 1".to_string(), 3), diff --git a/src/db.rs b/src/db.rs index 68a39c5a9c4..a416c73ebf8 100644 --- a/src/db.rs +++ b/src/db.rs @@ -75,8 +75,7 @@ pub fn tls_handshake() -> Box { } let mut builder = SslConnectorBuilder::new(SslMethod::tls()).unwrap(); - builder.builder_mut() - .set_verify(SSL_VERIFY_NONE); + builder.builder_mut().set_verify(SSL_VERIFY_NONE); Box::new(MyHandshake(builder.build())) } @@ -103,7 +102,9 @@ pub fn pool(url: &str, config: r2d2::Config) -> DieselPool { +pub fn diesel_pool(url: &str, + config: r2d2::Config) + -> DieselPool { let mut url = Url::parse(url).expect("Invalid database URL"); if env::var("HEROKU").is_ok() && !url.query_pairs().any(|(k, _)| k == "sslmode") { url.query_pairs_mut().append_pair("sslmode", "require"); @@ -143,11 +144,17 @@ impl Transaction { } } - pub fn conn(&self) -> CargoResult<&r2d2::PooledConnection> { + pub fn conn + (&self) + -> CargoResult<&r2d2::PooledConnection> { if !self.slot.filled() { - let conn = self.app.database.get().map_err(|e| { - internal(&format_args!("failed to get a database connection: {}", e)) - })?; + let conn = + self.app + .database + .get() + .map_err(|e| { + internal(&format_args!("failed to get a database connection: {}", e)) + })?; self.slot.fill(Box::new(conn)); } Ok(&**self.slot.borrow().unwrap()) @@ -183,23 +190,26 @@ impl Transaction { } impl Middleware for TransactionMiddleware { - fn before(&self, req: &mut Request) -> Result<(), Box> { + fn before(&self, req: &mut Request) -> Result<(), Box> { let app = req.app().clone(); req.mut_extensions().insert(Transaction::new(app)); Ok(()) } - fn after(&self, req: &mut Request, res: Result>) - -> Result> { - let tx = req.mut_extensions().pop::() - .expect("Transaction not present in request"); + fn after(&self, + req: &mut Request, + res: Result>) + -> Result> { + let tx = req.mut_extensions() + .pop::() + .expect("Transaction not present in request"); if let Some(transaction) = tx.tx.into_inner() { if res.is_ok() && tx.commit.get() == Some(true) { transaction.set_commit(); } - transaction.finish().map_err(|e| { - Box::new(e) as Box - })?; + transaction + .finish() + .map_err(|e| Box::new(e) as Box)?; } res } @@ -225,24 +235,26 @@ pub trait RequestTransaction { impl RequestTransaction for T { fn db_conn(&self) -> CargoResult { - self.app().diesel_database.get() - .map_err(Into::into) + self.app().diesel_database.get().map_err(Into::into) } fn tx(&self) -> CargoResult<&GenericConnection> { - self.extensions().find::() + self.extensions() + .find::() .expect("Transaction not present in request") .tx() } fn rollback(&self) { - self.extensions().find::() + self.extensions() + .find::() .expect("Transaction not present in request") .rollback() } fn commit(&self) { - self.extensions().find::() + self.extensions() + .find::() .expect("Transaction not present in request") .commit() } diff --git a/src/dependency.rs b/src/dependency.rs index 08e3f3cc06f..59f06a927af 100644 --- a/src/dependency.rs +++ b/src/dependency.rs @@ -72,10 +72,15 @@ pub struct NewDependency<'a> { impl Dependency { // FIXME: Encapsulate this in a `NewDependency` struct #[cfg_attr(feature = "clippy", allow(too_many_arguments))] - pub fn insert(conn: &GenericConnection, version_id: i32, crate_id: i32, - req: &semver::VersionReq, kind: Kind, - optional: bool, default_features: bool, - features: &[String], target: &Option) + pub fn insert(conn: &GenericConnection, + version_id: i32, + crate_id: i32, + req: &semver::VersionReq, + kind: Kind, + optional: bool, + default_features: bool, + features: &[String], + target: &Option) -> CargoResult { let req = req.to_string(); let stmt = conn.prepare("INSERT INTO dependencies @@ -83,9 +88,14 @@ impl Dependency { default_features, features, target, kind) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *")?; - let rows = stmt.query(&[&version_id, &crate_id, &req, - &optional, &default_features, - &features, target, &(kind as i32)])?; + let rows = stmt.query(&[&version_id, + &crate_id, + &req, + &optional, + &default_features, + &features, + target, + &(kind as i32)])?; Ok(Model::from_row(&rows.iter().next().unwrap())) } @@ -108,65 +118,65 @@ impl Dependency { impl ReverseDependency { pub fn encodable(self) -> EncodableDependency { - self.dependency.encodable(&self.crate_name, Some(self.crate_downloads)) + self.dependency + .encodable(&self.crate_name, Some(self.crate_downloads)) } } -pub fn add_dependencies( - conn: &PgConnection, - deps: &[::upload::CrateDependency], - version_id: i32, -) -> CargoResult> { +pub fn add_dependencies(conn: &PgConnection, + deps: &[::upload::CrateDependency], + version_id: i32) + -> CargoResult> { use diesel::insert; - let git_and_new_dependencies = deps.iter().map(|dep| { - let krate = Crate::by_name(&dep.name).first::(&*conn) - .map_err(|_| { - human(&format_args!("no known crate named `{}`", &*dep.name)) - })?; - if dep.version_req == semver::VersionReq::parse("*").unwrap() { - return Err(human("wildcard (`*`) dependency constraints are not allowed \ + let git_and_new_dependencies = deps.iter() + .map(|dep| { + let krate = + Crate::by_name(&dep.name) + .first::(&*conn) + .map_err(|_| human(&format_args!("no known crate named `{}`", &*dep.name)))?; + if dep.version_req == semver::VersionReq::parse("*").unwrap() { + return Err(human("wildcard (`*`) dependency constraints are not allowed \ on crates.io. See http://doc.crates.io/faq.html#can-\ libraries-use--as-a-version-for-their-dependencies for more \ information")); - } - let features: Vec<_> = dep.features.iter().map(|s| &**s).collect(); - - Ok(( - git::Dependency { - name: dep.name.to_string(), - req: dep.version_req.to_string(), - features: features.iter().map(|s| s.to_string()).collect(), - optional: dep.optional, - default_features: dep.default_features, - target: dep.target.clone(), - kind: dep.kind.or(Some(Kind::Normal)), - }, - NewDependency { - version_id: version_id, - crate_id: krate.id, - req: dep.version_req.to_string(), - kind: dep.kind.unwrap_or(Kind::Normal) as i32, - optional: dep.optional, - default_features: dep.default_features, - features: features, - target: dep.target.as_ref().map(|s| &**s), } - )) - }).collect::, _>>()?; + let features: Vec<_> = dep.features.iter().map(|s| &**s).collect(); + + Ok((git::Dependency { + name: dep.name.to_string(), + req: dep.version_req.to_string(), + features: features.iter().map(|s| s.to_string()).collect(), + optional: dep.optional, + default_features: dep.default_features, + target: dep.target.clone(), + kind: dep.kind.or(Some(Kind::Normal)), + }, + NewDependency { + version_id: version_id, + crate_id: krate.id, + req: dep.version_req.to_string(), + kind: dep.kind.unwrap_or(Kind::Normal) as i32, + optional: dep.optional, + default_features: dep.default_features, + features: features, + target: dep.target.as_ref().map(|s| &**s), + })) + }) + .collect::, _>>()?; let (git_deps, new_dependencies): (Vec<_>, Vec<_>) = git_and_new_dependencies.into_iter().unzip(); - insert(&new_dependencies).into(dependencies::table) + insert(&new_dependencies) + .into(dependencies::table) .execute(conn)?; Ok(git_deps) } impl Queryable for Dependency { - type Row = (i32, i32, i32, String, bool, bool, Vec, Option, - i32); + type Row = (i32, i32, i32, String, bool, bool, Vec, Option, i32); fn build(row: Self::Row) -> Self { Dependency { @@ -183,7 +193,7 @@ impl Queryable for Dependency { 1 => Kind::Build, 2 => Kind::Dev, n => panic!("unknown kind: {}", n), - } + }, } } } @@ -205,11 +215,13 @@ impl Model for Dependency { 1 => Kind::Build, 2 => Kind::Dev, n => panic!("unknown kind: {}", n), - } + }, } } - fn table_name(_: Option) -> &'static str { "dependencies" } + fn table_name(_: Option) -> &'static str { + "dependencies" + } } impl Model for ReverseDependency { @@ -221,5 +233,7 @@ impl Model for ReverseDependency { } } - fn table_name(_: Option) -> &'static str { panic!("no table") } + fn table_name(_: Option) -> &'static str { + panic!("no table") + } } diff --git a/src/dist.rs b/src/dist.rs index 3ba232629bf..501fb51eff1 100644 --- a/src/dist.rs +++ b/src/dist.rs @@ -11,7 +11,7 @@ pub struct Middleware { dist: Static, } -impl Default for Middleware { +impl Default for Middleware { fn default() -> Middleware { Middleware { handler: None, @@ -27,7 +27,7 @@ impl AroundMiddleware for Middleware { } impl Handler for Middleware { - fn call(&self, req: &mut Request) -> Result> { + fn call(&self, req: &mut Request) -> Result> { // First, attempt to serve a static file. If we're missing a static // file, then keep going. match self.dist.call(req) { @@ -37,15 +37,17 @@ impl Handler for Middleware { // Second, if we're requesting html, then we've only got one page so // serve up that page. Otherwise proxy on to the rest of the app. - let wants_html = req.headers().find("Accept").map(|accept| { - accept.iter().any(|s| s.contains("html")) - }).unwrap_or(false); + let wants_html = req.headers() + .find("Accept") + .map(|accept| accept.iter().any(|s| s.contains("html"))) + .unwrap_or(false); if wants_html { - self.dist.call(&mut RequestProxy { - other: req, - path: Some("/index.html"), - method: None, - }) + self.dist + .call(&mut RequestProxy { + other: req, + path: Some("/index.html"), + method: None, + }) } else { self.handler.as_ref().unwrap().call(req) } diff --git a/src/download.rs b/src/download.rs index 0df4d0c8cee..cc5e6a4d952 100644 --- a/src/download.rs +++ b/src/download.rs @@ -21,7 +21,8 @@ pub struct VersionDownload { #[derive(Insertable)] #[table_name="version_downloads"] -struct NewVersionDownload(#[column_name(version_id)] i32); +struct NewVersionDownload(#[column_name(version_id)] + i32); #[derive(RustcEncodable, RustcDecodable)] pub struct EncodableVersionDownload { @@ -40,11 +41,12 @@ impl VersionDownload { // nothing else. We have lots of other counters, but they're // all updated later on via the update-downloads script. let new_download = NewVersionDownload(version); - let downloads_row = new_download - .on_conflict((version_id, date), do_update().set( - downloads.eq(downloads + 1) - )); - diesel::insert(&downloads_row).into(version_downloads).execute(conn)?; + let downloads_row = + new_download.on_conflict((version_id, date), + do_update().set(downloads.eq(downloads + 1))); + diesel::insert(&downloads_row) + .into(version_downloads) + .execute(conn)?; Ok(()) } @@ -70,5 +72,7 @@ impl Model for VersionDownload { } } - fn table_name(_: Option) -> &'static str { "version_downloads" } + fn table_name(_: Option) -> &'static str { + "version_downloads" + } } diff --git a/src/git.rs b/src/git.rs index ac97a3d1ab0..dd9c17cc157 100644 --- a/src/git.rs +++ b/src/git.rs @@ -34,14 +34,14 @@ pub struct Dependency { } fn index_file(base: &Path, name: &str) -> PathBuf { - let name = name.chars().flat_map(|c| c.to_lowercase()).collect::(); + let name = name.chars() + .flat_map(|c| c.to_lowercase()) + .collect::(); match name.len() { 1 => base.join("1").join(&name), 2 => base.join("2").join(&name), 3 => base.join("3").join(&name[..1]).join(&name), - _ => base.join(&name[0..2]) - .join(&name[2..4]) - .join(&name), + _ => base.join(&name[0..2]).join(&name[2..4]).join(&name), } } @@ -56,7 +56,8 @@ pub fn add_crate(app: &App, krate: &Crate) -> CargoResult<()> { fs::create_dir_all(dst.parent().unwrap())?; let mut prev = String::new(); if fs::metadata(&dst).is_ok() { - File::open(&dst).and_then(|mut f| f.read_to_string(&mut prev))?; + File::open(&dst) + .and_then(|mut f| f.read_to_string(&mut prev))?; } let s = json::encode(krate).unwrap(); let new = prev + &s; @@ -64,31 +65,31 @@ pub fn add_crate(app: &App, krate: &Crate) -> CargoResult<()> { f.write_all(new.as_bytes())?; f.write_all(b"\n")?; - Ok((format!("Updating crate `{}#{}`", krate.name, krate.vers), - dst.clone())) + Ok((format!("Updating crate `{}#{}`", krate.name, krate.vers), dst.clone())) }) } -pub fn yank(app: &App, krate: &str, version: &semver::Version, - yanked: bool) -> CargoResult<()> { +pub fn yank(app: &App, krate: &str, version: &semver::Version, yanked: bool) -> CargoResult<()> { let repo = app.git_repo.lock().unwrap(); let repo_path = repo.workdir().unwrap(); let dst = index_file(repo_path, krate); commit_and_push(&repo, || { let mut prev = String::new(); - File::open(&dst).and_then(|mut f| f.read_to_string(&mut prev))?; - let new = prev.lines().map(|line| { - let mut git_crate = json::decode::(line).map_err(|_| { - internal(&format_args!("couldn't decode: `{}`", line)) - })?; - if git_crate.name != krate || - git_crate.vers != version.to_string() { - return Ok(line.to_string()) - } - git_crate.yanked = Some(yanked); - Ok(json::encode(&git_crate).unwrap()) - }).collect::>>(); + File::open(&dst) + .and_then(|mut f| f.read_to_string(&mut prev))?; + let new = prev.lines() + .map(|line| { + let mut git_crate = + json::decode::(line) + .map_err(|_| internal(&format_args!("couldn't decode: `{}`", line)))?; + if git_crate.name != krate || git_crate.vers != version.to_string() { + return Ok(line.to_string()); + } + git_crate.yanked = Some(yanked); + Ok(json::encode(&git_crate).unwrap()) + }) + .collect::>>(); let new = new?.join("\n"); let mut f = File::create(&dst)?; f.write_all(new.as_bytes())?; @@ -116,8 +117,9 @@ fn commit_and_push(repo: &git2::Repository, mut f: F) -> CargoResult<()> // git add $file let mut index = repo.index()?; let mut repo_path = repo_path.iter(); - let dst = dst.iter().skip_while(|s| Some(*s) == repo_path.next()) - .collect::(); + let dst = dst.iter() + .skip_while(|s| Some(*s) == repo_path.next()) + .collect::(); index.add_path(&dst)?; index.write()?; let tree_id = index.write_tree()?; @@ -152,9 +154,11 @@ fn commit_and_push(repo: &git2::Repository, mut f: F) -> CargoResult<()> let mut callbacks = git2::RemoteCallbacks::new(); callbacks.credentials(credentials); - origin.update_tips(Some(&mut callbacks), true, - git2::AutotagOption::Unspecified, - None)?; + origin + .update_tips(Some(&mut callbacks), + true, + git2::AutotagOption::Unspecified, + None)?; // Ok, we need to update, so fetch and reset --hard origin.fetch(&["refs/heads/*:refs/heads/*"], None, None)?; @@ -166,13 +170,12 @@ fn commit_and_push(repo: &git2::Repository, mut f: F) -> CargoResult<()> Err(internal("Too many rebase failures")) } -pub fn credentials(_user: &str, _user_from_url: Option<&str>, +pub fn credentials(_user: &str, + _user_from_url: Option<&str>, _cred: git2::CredentialType) -> Result { match (env::var("GIT_HTTP_USER"), env::var("GIT_HTTP_PWD")) { - (Ok(u), Ok(p)) => { - git2::Cred::userpass_plaintext(&u, &p) - } - _ => Err(git2::Error::from_str("no authentication set")) + (Ok(u), Ok(p)) => git2::Cred::userpass_plaintext(&u, &p), + _ => Err(git2::Error::from_str("no authentication set")), } } diff --git a/src/http.rs b/src/http.rs index a62cd3ad1b7..e45572b87cc 100644 --- a/src/http.rs +++ b/src/http.rs @@ -10,15 +10,18 @@ use std::str; /// Does all the nonsense for sending a GET to Github. Doesn't handle parsing /// because custom error-code handling may be desirable. Use /// `parse_github_response` to handle the "common" processing of responses. -pub fn github(app: &App, url: &str, auth: &Token) - -> Result<(Easy, Vec), curl::Error> { +pub fn github(app: &App, url: &str, auth: &Token) -> Result<(Easy, Vec), curl::Error> { let url = format!("{}://api.github.com{}", app.config.api_protocol, url); info!("GITHUB HTTP: {}", url); let mut headers = List::new(); - headers.append("Accept: application/vnd.github.v3+json").unwrap(); + headers + .append("Accept: application/vnd.github.v3+json") + .unwrap(); headers.append("User-Agent: hello!").unwrap(); - headers.append(&format!("Authorization: token {}", auth.access_token)).unwrap(); + headers + .append(&format!("Authorization: token {}", auth.access_token)) + .unwrap(); let mut handle = app.handle(); handle.url(&url).unwrap(); @@ -28,18 +31,19 @@ pub fn github(app: &App, url: &str, auth: &Token) let mut data = Vec::new(); { let mut transfer = handle.transfer(); - transfer.write_function(|buf| { - data.extend_from_slice(buf); - Ok(buf.len()) - }).unwrap(); + transfer + .write_function(|buf| { + data.extend_from_slice(buf); + Ok(buf.len()) + }) + .unwrap(); transfer.perform()?; } Ok((handle, data)) } /// Checks for normal responses -pub fn parse_github_response(mut resp: Easy, data: &[u8]) - -> CargoResult { +pub fn parse_github_response(mut resp: Easy, data: &[u8]) -> CargoResult { match resp.response_code().unwrap() { 200 => {} // Ok! 403 => { @@ -58,13 +62,11 @@ pub fn parse_github_response(mut resp: Easy, data: &[u8]) } } - let json = str::from_utf8(data).ok().chain_error(|| { - internal("github didn't send a utf8-response") - })?; + let json = str::from_utf8(data) + .ok() + .chain_error(|| internal("github didn't send a utf8-response"))?; - json::decode(json).chain_error(|| { - internal("github didn't send a valid json response") - }) + json::decode(json).chain_error(|| internal("github didn't send a valid json response")) } /// Gets a token with the given string as the access token, but all diff --git a/src/keyword.rs b/src/keyword.rs index 6c53d5877ad..c4c8a377d9f 100644 --- a/src/keyword.rs +++ b/src/keyword.rs @@ -40,8 +40,7 @@ pub struct EncodableKeyword { } impl Keyword { - pub fn find_by_keyword(conn: &PgConnection, name: &str) - -> QueryResult { + pub fn find_by_keyword(conn: &PgConnection, name: &str) -> QueryResult { keywords::table .filter(keywords::keyword.eq(::lower(name))) .first(&*conn) @@ -57,11 +56,10 @@ impl Keyword { keyword: &'a str, } - let lowercase_names: Vec<_> = names.iter() - .map(|s| s.to_lowercase()) - .collect(); + let lowercase_names: Vec<_> = names.iter().map(|s| s.to_lowercase()).collect(); - let new_keywords: Vec<_> = lowercase_names.iter() + let new_keywords: Vec<_> = lowercase_names + .iter() .map(|s| NewKeyword { keyword: s }) .collect(); @@ -77,14 +75,22 @@ impl Keyword { } pub fn valid_name(name: &str) -> bool { - if name.is_empty() { return false } + if name.is_empty() { + return false; + } name.chars().next().unwrap().is_alphanumeric() && - name.chars().all(|c| c.is_alphanumeric() || c == '_' || c == '-') && - name.chars().all(|c| c.is_ascii()) + name.chars() + .all(|c| c.is_alphanumeric() || c == '_' || c == '-') && + name.chars().all(|c| c.is_ascii()) } pub fn encodable(self) -> EncodableKeyword { - let Keyword { crates_cnt, keyword, created_at, .. } = self; + let Keyword { + crates_cnt, + keyword, + created_at, + .. + } = self; EncodableKeyword { id: keyword.clone(), created_at: ::encode_time(created_at), @@ -93,17 +99,22 @@ impl Keyword { } } - pub fn update_crate(conn: &PgConnection, - krate: &Crate, - keywords: &[&str]) -> QueryResult<()> { + pub fn update_crate(conn: &PgConnection, krate: &Crate, keywords: &[&str]) -> QueryResult<()> { conn.transaction(|| { let keywords = Keyword::find_or_create_all(conn, keywords)?; diesel::delete(CrateKeyword::belonging_to(krate)) .execute(conn)?; - let crate_keywords = keywords.into_iter().map(|kw| { - CrateKeyword { crate_id: krate.id, keyword_id: kw.id } - }).collect::>(); - diesel::insert(&crate_keywords).into(crates_keywords::table) + let crate_keywords = keywords + .into_iter() + .map(|kw| { + CrateKeyword { + crate_id: krate.id, + keyword_id: kw.id, + } + }) + .collect::>(); + diesel::insert(&crate_keywords) + .into(crates_keywords::table) .execute(conn)?; Ok(()) }) @@ -119,7 +130,9 @@ impl Model for Keyword { keyword: row.get("keyword"), } } - fn table_name(_: Option) -> &'static str { "keywords" } + fn table_name(_: Option) -> &'static str { + "keywords" + } } /// Handles the `GET /keywords` route. @@ -148,17 +161,23 @@ pub fn index(req: &mut Request) -> CargoResult { let data = query.load::<(Keyword, i64)>(&*conn)?; let total = data.get(0).map(|&(_, t)| t).unwrap_or(0); let kws = data.into_iter() - .map(|(k, _)| k.encodable()).collect::>(); + .map(|(k, _)| k.encodable()) + .collect::>(); #[derive(RustcEncodable)] - struct R { keywords: Vec, meta: Meta } + struct R { + keywords: Vec, + meta: Meta, + } #[derive(RustcEncodable)] - struct Meta { total: i64 } + struct Meta { + total: i64, + } Ok(req.json(&R { - keywords: kws, - meta: Meta { total: total }, - })) + keywords: kws, + meta: Meta { total: total }, + })) } /// Handles the `GET /keywords/:keyword_id` route. @@ -169,6 +188,8 @@ pub fn show(req: &mut Request) -> CargoResult { let kw = Keyword::find_by_keyword(&conn, name)?; #[derive(RustcEncodable)] - struct R { keyword: EncodableKeyword } + struct R { + keyword: EncodableKeyword, + } Ok(req.json(&R { keyword: kw.encodable() })) } diff --git a/src/krate.rs b/src/krate.rs index 9323825567c..2c5e49bf6e2 100644 --- a/src/krate.rs +++ b/src/krate.rs @@ -56,16 +56,31 @@ pub struct Crate { /// We literally never want to select `textsearchable_index_col` /// so we provide this type and constant to pass to `.select` -type AllColumns = (crates::id, crates::name, crates::updated_at, - crates::created_at, crates::downloads, crates::description, - crates::homepage, crates::documentation, crates::readme, crates::license, - crates::repository, crates::max_upload_size); - -pub const ALL_COLUMNS: AllColumns = (crates::id, crates::name, - crates::updated_at, crates::created_at, crates::downloads, - crates::description, crates::homepage, crates::documentation, - crates::readme, crates::license, crates::repository, - crates::max_upload_size); +type AllColumns = (crates::id, + crates::name, + crates::updated_at, + crates::created_at, + crates::downloads, + crates::description, + crates::homepage, + crates::documentation, + crates::readme, + crates::license, + crates::repository, + crates::max_upload_size); + +pub const ALL_COLUMNS: AllColumns = (crates::id, + crates::name, + crates::updated_at, + crates::created_at, + crates::downloads, + crates::description, + crates::homepage, + crates::documentation, + crates::readme, + crates::license, + crates::repository, + crates::max_upload_size); pub const MAX_NAME_LENGTH: usize = 64; @@ -115,12 +130,11 @@ pub struct NewCrate<'a> { } impl<'a> NewCrate<'a> { - pub fn create_or_update( - mut self, - conn: &PgConnection, - license_file: Option<&str>, - uploader: i32, - ) -> CargoResult { + pub fn create_or_update(mut self, + conn: &PgConnection, + license_file: Option<&str>, + uploader: i32) + -> CargoResult { use diesel::update; self.validate(license_file)?; @@ -130,13 +144,14 @@ impl<'a> NewCrate<'a> { // To avoid race conditions, we try to insert // first so we know whether to add an owner if let Some(krate) = self.save_new_crate(conn, uploader)? { - return Ok(krate) + return Ok(krate); } - let target = crates::table.filter( - canon_crate_name(crates::name) - .eq(canon_crate_name(self.name))); - update(target).set(&self) + let target = + crates::table + .filter(canon_crate_name(crates::name).eq(canon_crate_name(self.name))); + update(target) + .set(&self) .returning(ALL_COLUMNS) .get_result(conn) .map_err(Into::into) @@ -147,19 +162,21 @@ impl<'a> NewCrate<'a> { fn validate_url(url: Option<&str>, field: &str) -> CargoResult<()> { let url = match url { Some(s) => s, - None => return Ok(()) + None => return Ok(()), }; let url = Url::parse(url).map_err(|_| { human(&format_args!("`{}` is not a valid url: `{}`", field, url)) })?; match &url.scheme()[..] { "http" | "https" => {} - s => return Err(human(&format_args!("`{}` has an invalid url \ + s => { + return Err(human(&format_args!("`{}` has an invalid url \ scheme: `{}`", field, s))) + } } if url.cannot_be_a_base() { return Err(human(&format_args!("`{}` must have relative scheme \ - data: {}", field, url))) + data: {}", field, url))); } Ok(()) } @@ -174,10 +191,12 @@ impl<'a> NewCrate<'a> { fn validate_license(&mut self, license_file: Option<&str>) -> CargoResult<()> { if let Some(license) = self.license { for part in license.split('/') { - license_exprs::validate_license_expr(part) - .map_err(|e| human(&format_args!("{}; see http://opensource.org/licenses \ + license_exprs::validate_license_expr(part) + .map_err(|e| { + human(&format_args!("{}; see http://opensource.org/licenses \ for options, and http://spdx.org/licenses/ \ - for their identifiers", e)))?; + for their identifiers", e)) + })?; } } else if license_file.is_some() { // If no license is given, but a license file is given, flag this @@ -193,9 +212,10 @@ impl<'a> NewCrate<'a> { use diesel::select; use diesel::expression::dsl::exists; - let reserved_name = select(exists(reserved_crate_names - .filter(canon_crate_name(name).eq(canon_crate_name(self.name))) - )).get_result::(conn)?; + let reserved_name = + select(exists(reserved_crate_names + .filter(canon_crate_name(name).eq(canon_crate_name(self.name))))) + .get_result::(conn)?; if reserved_name { Err(human("cannot upload a crate with a reserved name")) } else { @@ -208,7 +228,8 @@ impl<'a> NewCrate<'a> { use diesel::insert; conn.transaction(|| { - let maybe_inserted = insert(&self.on_conflict_do_nothing()).into(crates) + let maybe_inserted = insert(&self.on_conflict_do_nothing()) + .into(crates) .returning(ALL_COLUMNS) .get_result::(conn) .optional()?; @@ -220,8 +241,7 @@ impl<'a> NewCrate<'a> { created_by: user_id, owner_kind: OwnerKind::User as i32, }; - insert(&owner).into(crate_owners::table) - .execute(conn)?; + insert(&owner).into(crate_owners::table).execute(conn)?; } Ok(maybe_inserted) @@ -232,18 +252,15 @@ impl<'a> NewCrate<'a> { impl Crate { pub fn by_name(name: &str) -> CrateQuery { Crate::all() - .filter( - canon_crate_name(crates::name).eq( - canon_crate_name(name)) - ).into_boxed() + .filter(canon_crate_name(crates::name).eq(canon_crate_name(name))) + .into_boxed() } pub fn all() -> Select { crates::table.select(ALL_COLUMNS) } - pub fn find_by_name(conn: &GenericConnection, - name: &str) -> CargoResult { + pub fn find_by_name(conn: &GenericConnection, name: &str) -> CargoResult { let stmt = conn.prepare("SELECT * FROM crates \ WHERE canon_crate_name(name) = canon_crate_name($1) LIMIT 1")?; @@ -304,10 +321,13 @@ impl Crate { WHERE canon_crate_name(name) = canon_crate_name($7) RETURNING *")?; - let rows = stmt.query(&[&documentation, &homepage, - &description, &readme, - &license, &repository, - &name])?; + let rows = stmt.query(&[&documentation, + &homepage, + &description, + &readme, + &license, + &repository, + &name])?; if let Some(row) = rows.iter().next() { return Ok(Model::from_row(&row)); } @@ -317,7 +337,7 @@ impl Crate { canon_crate_name($1)")?; let rows = stmt.query(&[&name])?; if !rows.is_empty() { - return Err(human("cannot upload a crate with a reserved name")) + return Err(human("cannot upload a crate with a reserved name")); } let stmt = conn.prepare("INSERT INTO crates @@ -326,12 +346,17 @@ impl Crate { repository, license, max_upload_size) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *")?; - let rows = stmt.query(&[&name, &description, &homepage, - &documentation, &readme, - &repository, &license, &max_upload_size])?; - let ret: Crate = Model::from_row(&rows.iter().next().chain_error(|| { - internal("no crate returned") - })?); + let rows = stmt.query(&[&name, + &description, + &homepage, + &documentation, + &readme, + &repository, + &license, + &max_upload_size])?; + let ret: Crate = Model::from_row(&rows.iter() + .next() + .chain_error(|| internal("no crate returned"))?); conn.execute("INSERT INTO crate_owners (crate_id, owner_id, created_by, owner_kind) @@ -342,47 +367,54 @@ impl Crate { fn validate_url(url: Option<&str>, field: &str) -> CargoResult<()> { let url = match url { Some(s) => s, - None => return Ok(()) + None => return Ok(()), }; let url = Url::parse(url).map_err(|_| { human(&format_args!("`{}` is not a valid url: `{}`", field, url)) })?; match &url.scheme()[..] { "http" | "https" => {} - s => return Err(human(&format_args!("`{}` has an invalid url \ + s => { + return Err(human(&format_args!("`{}` has an invalid url \ scheme: `{}`", field, s))) + } } if url.cannot_be_a_base() { return Err(human(&format_args!("`{}` must have relative scheme \ - data: {}", field, url))) + data: {}", field, url))); } Ok(()) } fn validate_license(license: Option<&str>) -> CargoResult<()> { - license.iter().flat_map(|s| s.split('/')) - .map(license_exprs::validate_license_expr) - .collect::, _>>() - .map(|_| ()) - .map_err(|e| human(&format_args!("{}; see http://opensource.org/licenses \ + license + .iter() + .flat_map(|s| s.split('/')) + .map(license_exprs::validate_license_expr) + .collect::, _>>() + .map(|_| ()) + .map_err(|e| { + human(&format_args!("{}; see http://opensource.org/licenses \ for options, and http://spdx.org/licenses/ \ - for their identifiers", e))) + for their identifiers", e)) + }) } } pub fn valid_name(name: &str) -> bool { - let under_max_length = name.chars() - .take(MAX_NAME_LENGTH + 1) - .count() <= MAX_NAME_LENGTH; + let under_max_length = name.chars().take(MAX_NAME_LENGTH + 1).count() <= MAX_NAME_LENGTH; Crate::valid_ident(name) && under_max_length } fn valid_ident(name: &str) -> bool { - if name.is_empty() { return false } + if name.is_empty() { + return false; + } name.chars().next().unwrap().is_alphabetic() && - name.chars().all(|c| c.is_alphanumeric() || c == '_' || c == '-') && - name.chars().all(|c| c.is_ascii()) + name.chars() + .all(|c| c.is_alphanumeric() || c == '_' || c == '-') && + name.chars().all(|c| c.is_ascii()) } pub fn valid_feature_name(name: &str) -> bool { @@ -401,7 +433,9 @@ impl Crate { pub fn minimal_encodable(self, max_version: semver::Version, - badges: Option>, exact_match: bool) -> EncodableCrate { + badges: Option>, + exact_match: bool) + -> EncodableCrate { self.encodable(max_version, None, None, None, badges, exact_match) } @@ -414,8 +448,16 @@ impl Crate { exact_match: bool) -> EncodableCrate { let Crate { - name, created_at, updated_at, downloads, description, - homepage, documentation, license, repository, .. + name, + created_at, + updated_at, + downloads, + description, + homepage, + documentation, + license, + repository, + .. } = self; let versions_link = match versions { Some(..) => None, @@ -423,9 +465,7 @@ impl Crate { }; let keyword_ids = keywords.map(|kws| kws.iter().map(|kw| kw.keyword.clone()).collect()); let category_ids = categories.map(|cats| cats.iter().map(|cat| cat.slug.clone()).collect()); - let badges = badges.map(|bs| { - bs.into_iter().map(|b| b.encodable()).collect() - }); + let badges = badges.map(|bs| bs.into_iter().map(|b| b.encodable()).collect()); EncodableCrate { id: name.clone(), name: name.clone(), @@ -447,7 +487,7 @@ impl Crate { version_downloads: format!("/api/v1/crates/{}/downloads", name), versions: versions_link, owners: Some(format!("/api/v1/crates/{}/owners", name)), - reverse_dependencies: format!("/api/v1/crates/{}/reverse_dependencies", name) + reverse_dependencies: format!("/api/v1/crates/{}/reverse_dependencies", name), }, } } @@ -455,7 +495,8 @@ impl Crate { pub fn max_version(&self, conn: &PgConnection) -> CargoResult { use schema::versions::dsl::*; - let vs = Version::belonging_to(self).select(num) + let vs = Version::belonging_to(self) + .select(num) .filter(yanked.eq(false)) .load::(conn)? .into_iter() @@ -467,31 +508,33 @@ impl Crate { let stmt = conn.prepare("SELECT num FROM versions WHERE crate_id = $1 AND yanked = 'f'")?; let rows = stmt.query(&[&self.id])?; - Ok(Version::max(rows.iter().map(|r| r.get::<_, String>("num")) - .map(|s| semver::Version::parse(&s).unwrap()))) + Ok(Version::max(rows.iter() + .map(|r| r.get::<_, String>("num")) + .map(|s| semver::Version::parse(&s).unwrap()))) } pub fn versions(&self, conn: &GenericConnection) -> CargoResult> { let stmt = conn.prepare("SELECT * FROM versions \ WHERE crate_id = $1")?; let rows = stmt.query(&[&self.id])?; - let mut ret = rows.iter().map(|r| { - Model::from_row(&r) - }).collect::>(); + let mut ret = rows.iter() + .map(|r| Model::from_row(&r)) + .collect::>(); ret.sort_by(|a, b| b.num.cmp(&a.num)); Ok(ret) } pub fn owners(&self, conn: &PgConnection) -> CargoResult> { - let base_query = CrateOwner::belonging_to(self) - .filter(crate_owners::deleted.eq(false)); - let users = base_query.inner_join(users::table) + let base_query = CrateOwner::belonging_to(self).filter(crate_owners::deleted.eq(false)); + let users = base_query + .inner_join(users::table) .select(users::all_columns) .filter(crate_owners::owner_kind.eq(OwnerKind::User as i32)) .load(conn)? .into_iter() .map(Owner::User); - let teams = base_query.inner_join(teams::table) + let teams = base_query + .inner_join(teams::table) .select(teams::all_columns) .filter(crate_owners::owner_kind.eq(OwnerKind::Team as i32)) .load(conn)? @@ -524,26 +567,29 @@ impl Crate { Ok(owners) } - pub fn owner_add( - &self, - app: &App, - conn: &PgConnection, - req_user: &User, - login: &str, - ) -> CargoResult<()> { + pub fn owner_add(&self, + app: &App, + conn: &PgConnection, + req_user: &User, + login: &str) + -> CargoResult<()> { let owner = match Owner::find_by_login(conn, login) { - Ok(owner @ Owner::User(_)) => { owner } - Ok(Owner::Team(team)) => if team.contains_user(app, req_user)? { - Owner::Team(team) - } else { - return Err(human(&format_args!("only members of {} can add it as \ + Ok(owner @ Owner::User(_)) => owner, + Ok(Owner::Team(team)) => { + if team.contains_user(app, req_user)? { + Owner::Team(team) + } else { + return Err(human(&format_args!("only members of {} can add it as \ an owner", login))); - }, - Err(err) => if login.contains(':') { - Owner::Team(Team::create(app, conn, login, req_user)?) - } else { - return Err(err); - }, + } + } + Err(err) => { + if login.contains(':') { + Owner::Team(Team::create(app, conn, login, req_user)?) + } else { + return Err(err); + } + } }; let crate_owner = CrateOwner { @@ -552,11 +598,10 @@ impl Crate { created_by: req_user.id, owner_kind: owner.kind() as i32, }; - diesel::insert(&crate_owner.on_conflict( - crate_owners::table.primary_key(), - do_update().set(crate_owners::deleted.eq(false)), - )).into(crate_owners::table) - .execute(conn)?; + diesel::insert(&crate_owner.on_conflict(crate_owners::table.primary_key(), + do_update().set(crate_owners::deleted.eq(false)))) + .into(crate_owners::table) + .execute(conn)?; Ok(()) } @@ -564,16 +609,14 @@ impl Crate { pub fn owner_remove(&self, conn: &PgConnection, _req_user: &User, - login: &str) -> CargoResult<()> { - let owner = Owner::find_by_login(conn, login).map_err(|_| { - human(&format_args!("could not find owner with login `{}`", login)) - })?; - let target = crate_owners::table.find(( - self.id(), - owner.id(), - owner.kind() as i32, - )); - diesel::update(target).set(crate_owners::deleted.eq(true)) + login: &str) + -> CargoResult<()> { + let owner = + Owner::find_by_login(conn, login) + .map_err(|_| human(&format_args!("could not find owner with login `{}`", login)))?; + let target = crate_owners::table.find((self.id(), owner.id(), owner.kind() as i32)); + diesel::update(target) + .set(crate_owners::deleted.eq(true)) .execute(conn)?; Ok(()) } @@ -585,7 +628,7 @@ impl Crate { authors: &[String]) -> CargoResult { if Version::find_by_num(conn, self.id, ver)?.is_some() { - return Err(human(&format_args!("crate version `{}` is already uploaded", ver))) + return Err(human(&format_args!("crate version `{}` is already uploaded", ver))); } Version::insert(conn, self.id, ver, features, authors) } @@ -610,7 +653,9 @@ impl Crate { } pub fn badges(&self, conn: &PgConnection) -> QueryResult> { - badges::table.filter(badges::crate_id.eq(self.id)).load(conn) + badges::table + .filter(badges::crate_id.eq(self.id)) + .load(conn) } /// Returns (dependency, dependent crate name, dependent crate downloads) @@ -627,10 +672,7 @@ impl Crate { } else { rows.get(0).get("total") }; - let vec: Vec<_> = rows - .iter() - .map(|r| Model::from_row(&r)) - .collect(); + let vec: Vec<_> = rows.iter().map(|r| Model::from_row(&r)).collect(); Ok((vec, cnt)) } @@ -653,7 +695,9 @@ impl Model for Crate { max_upload_size: row.get("max_upload_size"), } } - fn table_name(_: Option) -> &'static str { "crates" } + fn table_name(_: Option) -> &'static str { + "crates" + } } /// Handles the `GET /crates` route. @@ -683,7 +727,9 @@ pub fn index(req: &mut Request) -> CargoResult { let q = plainto_tsquery(q_string); query = query.filter(q.matches(crates::textsearchable_index_col)); - query = query.select((ALL_COLUMNS, sql::("COUNT(*) OVER()"), crates::name.eq(q_string))); + query = + query + .select((ALL_COLUMNS, sql::("COUNT(*) OVER()"), crates::name.eq(q_string))); let perfect_match = crates::name.eq(q_string).desc(); if sort == "downloads" { query = query.order((perfect_match, crates::downloads.desc())); @@ -703,32 +749,34 @@ pub fn index(req: &mut Request) -> CargoResult { } if let Some(kw) = params.get("keyword") { - query = query.filter(crates::id.eq_any( - crates_keywords::table.select(crates_keywords::crate_id) - .inner_join(keywords::table) - .filter(::lower(keywords::keyword).eq(::lower(kw))) - )); + query = query.filter(crates::id.eq_any(crates_keywords::table + .select(crates_keywords::crate_id) + .inner_join(keywords::table) + .filter(::lower(keywords::keyword) + .eq(::lower(kw))))); } else if let Some(letter) = params.get("letter") { let pattern = format!("{}%", letter.chars().next().unwrap() .to_lowercase().collect::()); query = query.filter(canon_crate_name(crates::name).like(pattern)); - } - else if let Some(user_id) = params.get("user_id").and_then(|s| s.parse::().ok()) { - query = query.filter(crates::id.eq_any( - crate_owners::table.select(crate_owners::crate_id) - .filter(crate_owners::owner_id.eq(user_id)) - .filter(crate_owners::owner_kind.eq(OwnerKind::User as i32)) - )); + } else if let Some(user_id) = params.get("user_id").and_then(|s| s.parse::().ok()) { + query = + query.filter(crates::id.eq_any(crate_owners::table + .select(crate_owners::crate_id) + .filter(crate_owners::owner_id.eq(user_id)) + .filter(crate_owners::owner_kind + .eq(OwnerKind::User as i32)))); } else if params.get("following").is_some() { - query = query.filter(crates::id.eq_any( - follows::table.select(follows::crate_id) - .filter(follows::user_id.eq(req.user()?.id)) - )); + query = query.filter(crates::id.eq_any(follows::table + .select(follows::crate_id) + .filter(follows::user_id + .eq(req.user()?.id)))); } let data = query.load::<(Crate, i64, bool)>(&*conn)?; let total = data.get(0).map(|&(_, t, _)| t).unwrap_or(0); - let crates = data.iter().map(|&(ref c, _, _)| c.clone()).collect::>(); + let crates = data.iter() + .map(|&(ref c, _, _)| c.clone()) + .collect::>(); let perfect_matches = data.into_iter().map(|(_, _, b)| b).collect::>(); let versions = Version::belonging_to(&crates) @@ -737,23 +785,33 @@ pub fn index(req: &mut Request) -> CargoResult { .into_iter() .map(|versions| Version::max(versions.into_iter().map(|v| v.num))); - let crates = versions.zip(crates).zip(perfect_matches).map(|((max_version, krate), perfect_match)| { - // FIXME: If we add crate_id to the Badge enum we can eliminate - // this N+1 - let badges = badges::table.filter(badges::crate_id.eq(krate.id)) - .load::(&*conn)?; - Ok(krate.minimal_encodable(max_version, Some(badges), perfect_match)) - }).collect::>()?; + let crates = versions + .zip(crates) + .zip(perfect_matches) + .map(|((max_version, krate), perfect_match)| { + // FIXME: If we add crate_id to the Badge enum we can eliminate + // this N+1 + let badges = badges::table + .filter(badges::crate_id.eq(krate.id)) + .load::(&*conn)?; + Ok(krate.minimal_encodable(max_version, Some(badges), perfect_match)) + }) + .collect::>()?; #[derive(RustcEncodable)] - struct R { crates: Vec, meta: Meta } + struct R { + crates: Vec, + meta: Meta, + } #[derive(RustcEncodable)] - struct Meta { total: i64 } + struct Meta { + total: i64, + } Ok(req.json(&R { - crates: crates, - meta: Meta { total: total }, - })) + crates: crates, + meta: Meta { total: total }, + })) } /// Handles the `GET /summary` route. @@ -762,7 +820,8 @@ pub fn summary(req: &mut Request) -> CargoResult { let conn = req.db_conn()?; let num_crates = crates.count().get_result(&*conn)?; - let num_downloads = metadata::table.select(metadata::total_downloads) + let num_downloads = metadata::table + .select(metadata::total_downloads) .get_result(&*conn)?; let encode_crates = |krates: Vec| -> CargoResult> { @@ -773,26 +832,29 @@ pub fn summary(req: &mut Request) -> CargoResult { .into_iter() .map(|versions| Version::max(versions.into_iter().map(|v| v.num))) .zip(krates) - .map(|(max_version, krate)| { - Ok(krate.minimal_encodable(max_version, None, false)) - }).collect() + .map(|(max_version, krate)| Ok(krate.minimal_encodable(max_version, None, false))) + .collect() }; - let new_crates = crates.order(created_at.desc()) + let new_crates = crates + .order(created_at.desc()) .select(ALL_COLUMNS) .limit(10) .load(&*conn)?; - let just_updated = crates.filter(updated_at.ne(created_at)) + let just_updated = crates + .filter(updated_at.ne(created_at)) .order(updated_at.desc()) .select(ALL_COLUMNS) .limit(10) .load(&*conn)?; - let most_downloaded = crates.order(downloads.desc()) + let most_downloaded = crates + .order(downloads.desc()) .select(ALL_COLUMNS) .limit(10) .load(&*conn)?; - let popular_keywords = keywords::table.order(keywords::crates_cnt.desc()) + let popular_keywords = keywords::table + .order(keywords::crates_cnt.desc()) .limit(10) .load(&*conn)? .into_iter() @@ -815,14 +877,14 @@ pub fn summary(req: &mut Request) -> CargoResult { popular_categories: Vec, } Ok(req.json(&R { - num_downloads: num_downloads, - num_crates: num_crates, - new_crates: encode_crates(new_crates)?, - most_downloaded: encode_crates(most_downloaded)?, - just_updated: encode_crates(just_updated)?, - popular_keywords: popular_keywords, - popular_categories: popular_categories, - })) + num_downloads: num_downloads, + num_crates: num_crates, + new_crates: encode_crates(new_crates)?, + most_downloaded: encode_crates(most_downloaded)?, + just_updated: encode_crates(just_updated)?, + popular_keywords: popular_keywords, + popular_categories: popular_categories, + })) } /// Handles the `GET /crates/:crate_id` route. @@ -844,7 +906,8 @@ pub fn show(req: &mut Request) -> CargoResult { .select(categories::all_columns) .load(&*conn)?; - let badges = badges::table.filter(badges::crate_id.eq(krate.id)) + let badges = badges::table + .filter(badges::crate_id.eq(krate.id)) .load(&*conn)?; let max_version = krate.max_version(&conn)?; @@ -856,15 +919,21 @@ pub fn show(req: &mut Request) -> CargoResult { categories: Vec, } Ok(req.json(&R { - krate: krate.clone().encodable( - max_version, Some(ids), Some(&kws), Some(&cats), Some(badges), false - ), - versions: versions.into_iter().map(|v| { - v.encodable(&krate.name) - }).collect(), - keywords: kws.into_iter().map(|k| k.encodable()).collect(), - categories: cats.into_iter().map(|k| k.encodable()).collect(), - })) + krate: krate + .clone() + .encodable(max_version, + Some(ids), + Some(&kws), + Some(&cats), + Some(badges), + false), + versions: versions + .into_iter() + .map(|v| v.encodable(&krate.name)) + .collect(), + keywords: kws.into_iter().map(|k| k.encodable()).collect(), + categories: cats.into_iter().map(|k| k.encodable()).collect(), + })) } /// Handles the `PUT /crates/new` route. @@ -874,15 +943,18 @@ pub fn new(req: &mut Request) -> CargoResult { let name = &*new_crate.name; let vers = &*new_crate.vers; - let features = new_crate.features.iter().map(|(k, v)| { - (k[..].to_string(), v.iter().map(|v| v[..].to_string()).collect()) - }).collect::>>(); - let keywords = new_crate.keywords.as_ref().map(|kws| { - kws.iter().map(|kw| &**kw).collect() - }).unwrap_or_else(Vec::new); - - let categories = new_crate.categories.as_ref().map(|s| &s[..]) - .unwrap_or(&[]); + let features = new_crate + .features + .iter() + .map(|(k, v)| (k[..].to_string(), v.iter().map(|v| v[..].to_string()).collect())) + .collect::>>(); + let keywords = new_crate + .keywords + .as_ref() + .map(|kws| kws.iter().map(|kw| &**kw).collect()) + .unwrap_or_else(Vec::new); + + let categories = new_crate.categories.as_ref().map(|s| &s[..]).unwrap_or(&[]); let categories: Vec<_> = categories.iter().map(|k| &**k).collect(); let conn = req.db_conn()?; @@ -904,20 +976,21 @@ pub fn new(req: &mut Request) -> CargoResult { let owners = krate.owners(&conn)?; if rights(req.app(), &owners, &user)? < Rights::Publish { return Err(human("crate name has already been claimed by \ - another user")) + another user")); } if krate.name != name { - return Err(human(&format_args!("crate was previously named `{}`", krate.name))) + return Err(human(&format_args!("crate was previously named `{}`", krate.name))); } - let length = req.content_length().chain_error(|| { - human("missing header: Content-Length") - })?; - let max = krate.max_upload_size.map(|m| m as u64) - .unwrap_or(app.config.max_upload_size); + let length = req.content_length() + .chain_error(|| human("missing header: Content-Length"))?; + let max = krate + .max_upload_size + .map(|m| m as u64) + .unwrap_or(app.config.max_upload_size); if length > max { - return Err(human(&format_args!("max upload size is: {}", max))) + return Err(human(&format_args!("max upload size is: {}", max))); } // Persist the new version of this crate @@ -936,11 +1009,7 @@ pub fn new(req: &mut Request) -> CargoResult { // Update all badges for this crate, collecting any invalid badges in // order to be able to warn about them - let ignored_invalid_badges = Badge::update_crate( - &conn, - &krate, - new_crate.badges.as_ref() - )?; + let ignored_invalid_badges = Badge::update_crate(&conn, &krate, new_crate.badges.as_ref())?; let max_version = krate.max_version(&conn)?; // Upload the crate, return way to delete the crate from the server @@ -957,9 +1026,10 @@ pub fn new(req: &mut Request) -> CargoResult { deps: git_deps, yanked: Some(false), }; - git::add_crate(&**req.app(), &git_crate).chain_error(|| { - internal(&format_args!("could not add crate `{}` to the git repo", name)) - })?; + git::add_crate(&**req.app(), &git_crate) + .chain_error(|| { + internal(&format_args!("could not add crate `{}` to the git repo", name)) + })?; // Now that we've come this far, we're committed! bomb.path = None; @@ -975,11 +1045,14 @@ pub fn new(req: &mut Request) -> CargoResult { }; #[derive(RustcEncodable)] - struct R<'a> { krate: EncodableCrate, warnings: Warnings<'a> } + struct R<'a> { + krate: EncodableCrate, + warnings: Warnings<'a>, + } Ok(req.json(&R { - krate: krate.minimal_encodable(max_version, None, false), - warnings: warnings - })) + krate: krate.minimal_encodable(max_version, None, false), + warnings: warnings, + })) }) } @@ -988,19 +1061,20 @@ fn parse_new_headers(req: &mut Request) -> CargoResult<(upload::NewCrate, User)> let amt = read_le_u32(req.body())? as u64; let max = req.app().config.max_upload_size; if amt > max { - return Err(human(&format_args!("max upload size is: {}", max))) + return Err(human(&format_args!("max upload size is: {}", max))); } let mut json = vec![0; amt as usize]; read_fill(req.body(), &mut json)?; - let json = String::from_utf8(json).map_err(|_| { - human("json body was not valid utf-8") - })?; - let new: upload::NewCrate = json::decode(&json).map_err(|e| { - human(&format_args!("invalid upload request: {:?}", e)) - })?; + let json = String::from_utf8(json) + .map_err(|_| human("json body was not valid utf-8"))?; + let new: upload::NewCrate = + json::decode(&json) + .map_err(|e| human(&format_args!("invalid upload request: {:?}", e)))?; // Make sure required fields are provided - fn empty(s: Option<&String>) -> bool { s.map_or(true, |s| s.is_empty()) } + fn empty(s: Option<&String>) -> bool { + s.map_or(true, |s| s.is_empty()) + } let mut missing = Vec::new(); if empty(new.description.as_ref()) { @@ -1037,15 +1111,18 @@ pub fn download(req: &mut Request) -> CargoResult { increment_download_counts(req, crate_name, version)?; } - let redirect_url = req.app().config.uploader - .crate_location(crate_name, version).ok_or_else(|| - human("crate files not found") - )?; + let redirect_url = req.app() + .config + .uploader + .crate_location(crate_name, version) + .ok_or_else(|| human("crate files not found"))?; if req.wants_json() { #[derive(RustcEncodable)] - struct R { url: String } - Ok(req.json(&R{ url: redirect_url })) + struct R { + url: String, + } + Ok(req.json(&R { url: redirect_url })) } else { Ok(req.redirect(redirect_url)) } @@ -1055,7 +1132,8 @@ fn increment_download_counts(req: &Request, crate_name: &str, version: &str) -> use self::versions::dsl::*; let conn = req.db_conn()?; - let version_id = versions.select(id) + let version_id = versions + .select(id) .filter(crate_id.eq_any(Crate::by_name(crate_name).select(crates::id))) .filter(num.eq(version)) .first(&*conn)?; @@ -1094,13 +1172,24 @@ pub fn downloads(req: &mut Request) -> CargoResult { .load::(&*conn)?; #[derive(RustcEncodable, Queryable)] - struct ExtraDownload { date: String, downloads: i64 } + struct ExtraDownload { + date: String, + downloads: i64, + } #[derive(RustcEncodable)] - struct R { version_downloads: Vec, meta: Meta } + struct R { + version_downloads: Vec, + meta: Meta, + } #[derive(RustcEncodable)] - struct Meta { extra_downloads: Vec } + struct Meta { + extra_downloads: Vec, + } let meta = Meta { extra_downloads: extra }; - Ok(req.json(&R{ version_downloads: downloads, meta: meta })) + Ok(req.json(&R { + version_downloads: downloads, + meta: meta, + })) } #[derive(Insertable, Queryable, Identifiable, Associations)] @@ -1116,13 +1205,11 @@ fn follow_target(req: &mut Request) -> CargoResult { let user = req.user()?; let conn = req.db_conn()?; let crate_name = &req.params()["crate_id"]; - let crate_id = Crate::by_name(crate_name) - .select(crates::id) - .first(&*conn)?; + let crate_id = Crate::by_name(crate_name).select(crates::id).first(&*conn)?; Ok(Follow { - user_id: user.id, - crate_id: crate_id, - }) + user_id: user.id, + crate_id: crate_id, + }) } /// Handles the `PUT /crates/:crate_id/follow` route. @@ -1133,7 +1220,9 @@ pub fn follow(req: &mut Request) -> CargoResult { .into(follows::table) .execute(&*conn)?; #[derive(RustcEncodable)] - struct R { ok: bool } + struct R { + ok: bool, + } Ok(req.json(&R { ok: true })) } @@ -1143,7 +1232,9 @@ pub fn unfollow(req: &mut Request) -> CargoResult { let conn = req.db_conn()?; diesel::delete(&follow).execute(&*conn)?; #[derive(RustcEncodable)] - struct R { ok: bool } + struct R { + ok: bool, + } Ok(req.json(&R { ok: true })) } @@ -1156,7 +1247,9 @@ pub fn following(req: &mut Request) -> CargoResult { let following = diesel::select(exists(follows::table.find(follow.id()))) .get_result(&*conn)?; #[derive(RustcEncodable)] - struct R { following: bool } + struct R { + following: bool, + } Ok(req.json(&R { following: following })) } @@ -1168,12 +1261,16 @@ pub fn versions(req: &mut Request) -> CargoResult { let tx = req.tx()?; let krate = Crate::find_by_name(tx, crate_name)?; let versions = krate.versions(tx)?; - let versions = versions.into_iter().map(|v| v.encodable(crate_name)) - .collect(); + let versions = versions + .into_iter() + .map(|v| v.encodable(crate_name)) + .collect(); #[derive(RustcEncodable)] - struct R { versions: Vec } - Ok(req.json(&R{ versions: versions })) + struct R { + versions: Vec, + } + Ok(req.json(&R { versions: versions })) } /// Handles the `GET /crates/:crate_id/owners` route. @@ -1181,14 +1278,17 @@ pub fn owners(req: &mut Request) -> CargoResult { let crate_name = &req.params()["crate_id"]; let conn = req.db_conn()?; let krate = Crate::by_name(crate_name).first::(&*conn)?; - let owners = krate.owners(&conn)? + let owners = krate + .owners(&conn)? .into_iter() .map(Owner::encodable) .collect(); #[derive(RustcEncodable)] - struct R { users: Vec } - Ok(req.json(&R{ users: owners })) + struct R { + users: Vec, + } + Ok(req.json(&R { users: owners })) } /// Handles the `PUT /crates/:crate_id/owners` route. @@ -1227,33 +1327,35 @@ fn modify_owners(req: &mut Request, add: bool) -> CargoResult { owners: Option>, } - let request: Request = json::decode(&body).map_err(|_| { - human("invalid json request") - })?; + let request: Request = json::decode(&body) + .map_err(|_| human("invalid json request"))?; - let logins = request.owners.or(request.users).ok_or_else(|| { - human("invalid json request") - })?; + let logins = request + .owners + .or(request.users) + .ok_or_else(|| human("invalid json request"))?; for login in &logins { if add { if owners.iter().any(|owner| owner.login() == *login) { - return Err(human(&format_args!("`{}` is already an owner", login))) + return Err(human(&format_args!("`{}` is already an owner", login))); } krate.owner_add(req.app(), &conn, user, login)?; } else { // Removing the team that gives you rights is prevented because // team members only have Rights::Publish if *login == user.gh_login { - return Err(human("cannot remove yourself as an owner")) + return Err(human("cannot remove yourself as an owner")); } krate.owner_remove(&conn, user, login)?; } } #[derive(RustcEncodable)] - struct R { ok: bool } - Ok(req.json(&R{ ok: true })) + struct R { + ok: bool, + } + Ok(req.json(&R { ok: true })) } /// Handles the `GET /crates/:crate_id/reverse_dependencies` route. @@ -1263,15 +1365,24 @@ pub fn reverse_dependencies(req: &mut Request) -> CargoResult { let krate = Crate::find_by_name(conn, name)?; let (offset, limit) = req.pagination(10, 100)?; let (rev_deps, total) = krate.reverse_dependencies(conn, offset, limit)?; - let rev_deps = rev_deps.into_iter() + let rev_deps = rev_deps + .into_iter() .map(ReverseDependency::encodable) .collect(); #[derive(RustcEncodable)] - struct R { dependencies: Vec, meta: Meta } + struct R { + dependencies: Vec, + meta: Meta, + } #[derive(RustcEncodable)] - struct Meta { total: i64 } - Ok(req.json(&R{ dependencies: rev_deps, meta: Meta { total: total } })) + struct Meta { + total: i64, + } + Ok(req.json(&R { + dependencies: rev_deps, + meta: Meta { total: total }, + })) } use diesel::types::{Text, Date}; diff --git a/src/lib.rs b/src/lib.rs index 25cf755e746..0c53049e973 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,11 +7,16 @@ #![cfg_attr(feature = "clippy", feature(plugin))] #![cfg_attr(feature = "clippy", plugin(clippy))] -#[macro_use] extern crate diesel; -#[macro_use] extern crate diesel_codegen; -#[macro_use] extern crate log; -#[macro_use] extern crate serde_json; -#[macro_use] extern crate serde_derive; +#[macro_use] +extern crate diesel; +#[macro_use] +extern crate diesel_codegen; +#[macro_use] +extern crate log; +#[macro_use] +extern crate serde_json; +#[macro_use] +extern crate serde_derive; extern crate chrono; extern crate curl; extern crate diesel_full_text_search; @@ -109,8 +114,10 @@ pub fn middleware(app: Arc) -> MiddlewareBuilder { api_router.put("/crates/new", C(krate::new)); api_router.get("/crates/:crate_id/:version", C(version::show)); api_router.get("/crates/:crate_id/:version/download", C(krate::download)); - api_router.get("/crates/:crate_id/:version/dependencies", C(version::dependencies)); - api_router.get("/crates/:crate_id/:version/downloads", C(version::downloads)); + api_router.get("/crates/:crate_id/:version/dependencies", + C(version::dependencies)); + api_router.get("/crates/:crate_id/:version/downloads", + C(version::downloads)); api_router.get("/crates/:crate_id/:version/authors", C(version::authors)); api_router.get("/crates/:crate_id/downloads", C(krate::downloads)); api_router.get("/crates/:crate_id/versions", C(krate::versions)); @@ -122,7 +129,8 @@ pub fn middleware(app: Arc) -> MiddlewareBuilder { api_router.delete("/crates/:crate_id/owners", C(krate::remove_owners)); api_router.delete("/crates/:crate_id/:version/yank", C(version::yank)); api_router.put("/crates/:crate_id/:version/unyank", C(version::unyank)); - api_router.get("/crates/:crate_id/reverse_dependencies", C(krate::reverse_dependencies)); + api_router.get("/crates/:crate_id/reverse_dependencies", + C(krate::reverse_dependencies)); api_router.get("/versions", C(version::index)); api_router.get("/versions/:version_id", C(version::show)); api_router.get("/keywords", C(keyword::index)); @@ -169,8 +177,7 @@ pub fn middleware(app: Arc) -> MiddlewareBuilder { m.around(util::Head::default()); m.add(conduit_conditional_get::ConditionalGet); m.add(conduit_cookie::Middleware::new(app.session_key.as_bytes())); - m.add(conduit_cookie::SessionMiddleware::new("cargo_session", - env == Env::Production)); + m.add(conduit_cookie::SessionMiddleware::new("cargo_session", env == Env::Production)); m.add(app::AppMiddleware::new(app)); if env != Env::Test { m.add(db::TransactionMiddleware); @@ -185,8 +192,7 @@ pub fn middleware(app: Arc) -> MiddlewareBuilder { struct DebugMiddleware; impl conduit_middleware::Middleware for DebugMiddleware { - fn before(&self, req: &mut conduit::Request) - -> Result<(), Box> { + fn before(&self, req: &mut conduit::Request) -> Result<(), Box> { println!(" version: {}", req.http_version()); println!(" method: {:?}", req.method()); println!(" scheme: {:?}", req.scheme()); @@ -199,9 +205,10 @@ pub fn middleware(app: Arc) -> MiddlewareBuilder { } Ok(()) } - fn after(&self, _req: &mut conduit::Request, - res: Result>) - -> Result> { + fn after(&self, + _req: &mut conduit::Request, + res: Result>) + -> Result> { res.map(|res| { println!(" <- {:?}", res.status); for (k, v) in &res.headers { @@ -223,9 +230,7 @@ pub fn encode_time(ts: time::Timespec) -> String { pub fn env(s: &str) -> String { dotenv::dotenv().ok(); - ::std::env::var(s).unwrap_or_else(|_| { - panic!("must have `{}` defined", s) - }) + ::std::env::var(s).unwrap_or_else(|_| panic!("must have `{}` defined", s)) } sql_function!(lower, lower_t, (x: ::diesel::types::Text) -> ::diesel::types::Text); diff --git a/src/owner.rs b/src/owner.rs index 70faa2d0987..bf7345deaa8 100644 --- a/src/owner.rs +++ b/src/owner.rs @@ -50,7 +50,6 @@ pub struct Team { /// Sugary goodness pub name: Option, pub avatar: Option, - } #[derive(RustcEncodable)] @@ -87,10 +86,12 @@ impl Team { "github" => { // Ok to unwrap since we know one ":" is contained let org = chunks.next().unwrap(); - let team = chunks.next().ok_or_else(|| - human("missing github team argument; \ + let team = chunks + .next() + .ok_or_else(|| { + human("missing github team argument; \ format is github:org:team") - )?; + })?; Team::create_github_team(app, conn, login, org, team, req_user) } _ => { @@ -103,8 +104,12 @@ impl Team { /// Tries to create a Github Team from scratch. Assumes `org` and `team` are /// correctly parsed out of the full `name`. `name` is passed as a /// convenience to avoid rebuilding it. - pub fn create_github_team(app: &App, conn: &PgConnection, login: &str, - org_name: &str, team_name: &str, req_user: &User) + pub fn create_github_team(app: &App, + conn: &PgConnection, + login: &str, + org_name: &str, + team_name: &str, + req_user: &User) -> CargoResult { // GET orgs/:org/teams // check that `team` is the `slug` in results, and grab its data @@ -113,7 +118,7 @@ impl Team { fn whitelist(c: &char) -> bool { match *c { 'a'...'z' | 'A'...'Z' | '0'...'9' | '-' | '_' => false, - _ => true + _ => true, } } @@ -124,9 +129,9 @@ impl Team { #[derive(RustcDecodable)] struct GithubTeam { - slug: String, // the name we want to find - id: i32, // unique GH id (needed for membership queries) - name: Option, // Pretty name + slug: String, // the name we want to find + id: i32, // unique GH id (needed for membership queries) + name: Option, // Pretty name } // FIXME: we just set per_page=100 and don't bother chasing pagination @@ -136,11 +141,13 @@ impl Team { let (handle, data) = http::github(app, &url, &token)?; let teams: Vec = http::parse_github_response(handle, &data)?; - let team = teams.into_iter().find(|team| team.slug == team_name) + let team = teams + .into_iter() + .find(|team| team.slug == team_name) .ok_or_else(|| { - human(&format_args!("could not find the github team {}/{}", + human(&format_args!("could not find the github team {}/{}", org_name, team_name)) - })?; + })?; if !team_with_gh_id_contains_user(app, team.id, req_user)? { return Err(human("only members of a team can add it as an owner")); @@ -181,9 +188,8 @@ impl Team { avatar: avatar, }; - diesel::insert( - &new_team.on_conflict(teams::github_id, do_update().set(&new_team)) - ).into(teams::table) + diesel::insert(&new_team.on_conflict(teams::github_id, do_update().set(&new_team))) + .into(teams::table) .get_result(conn) .map_err(Into::into) } @@ -197,8 +203,7 @@ impl Team { } } -fn team_with_gh_id_contains_user(app: &App, github_id: i32, user: &User) - -> CargoResult { +fn team_with_gh_id_contains_user(app: &App, github_id: i32, user: &User) -> CargoResult { // GET teams/:team_id/memberships/:user_name // check that "state": "active" @@ -214,7 +219,7 @@ fn team_with_gh_id_contains_user(app: &App, github_id: i32, user: &User) // Officially how `false` is returned if handle.response_code().unwrap() == 404 { - return Ok(false) + return Ok(false); } let membership: Membership = http::parse_github_response(handle, &resp)?; @@ -235,29 +240,28 @@ impl Model for Team { } } - fn table_name(_: Option) -> &'static str { "teams" } + fn table_name(_: Option) -> &'static str { + "teams" + } } impl Owner { /// Finds the owner by name, failing out if it doesn't exist. /// May be a user's GH login, or a full team name. This is case /// sensitive. - pub fn find_by_login(conn: &PgConnection, - name: &str) -> CargoResult { + pub fn find_by_login(conn: &PgConnection, name: &str) -> CargoResult { if name.contains(':') { - teams::table.filter(teams::login.eq(name)) + teams::table + .filter(teams::login.eq(name)) .first(conn) .map(Owner::Team) - .map_err(|_| - human(&format_args!("could not find team with name {}", name)) - ) + .map_err(|_| human(&format_args!("could not find team with name {}", name))) } else { - users::table.filter(users::gh_login.eq(name)) + users::table + .filter(users::gh_login.eq(name)) .first(conn) .map(Owner::User) - .map_err(|_| - human(&format_args!("could not find user with login `{}`", name)) - ) + .map_err(|_| human(&format_args!("could not find user with login `{}`", name))) } } @@ -284,7 +288,14 @@ impl Owner { pub fn encodable(self) -> EncodableOwner { match self { - Owner::User(User { id, email, name, gh_login, gh_avatar, .. }) => { + Owner::User(User { + id, + email, + name, + gh_login, + gh_avatar, + .. + }) => { let url = format!("https://github.com/{}", gh_login); EncodableOwner { id: id, @@ -296,7 +307,13 @@ impl Owner { kind: String::from("user"), } } - Owner::Team(Team { id, name, login, avatar, .. }) => { + Owner::Team(Team { + id, + name, + login, + avatar, + .. + }) => { let url = { let mut parts = login.split(':'); parts.next(); // discard github @@ -329,14 +346,17 @@ pub fn rights(app: &App, owners: &[Owner], user: &User) -> CargoResult { let mut best = Rights::None; for owner in owners { match *owner { - Owner::User(ref other_user) => if other_user.id == user.id { - return Ok(Rights::Full); - }, - Owner::Team(ref team) => if team.contains_user(app, user)? { - best = Rights::Publish; - }, + Owner::User(ref other_user) => { + if other_user.id == user.id { + return Ok(Rights::Full); + } + } + Owner::Team(ref team) => { + if team.contains_user(app, user)? { + best = Rights::Publish; + } + } } } Ok(best) } - diff --git a/src/tests/all.rs b/src/tests/all.rs index ce5fe12452e..d414b353668 100755 --- a/src/tests/all.rs +++ b/src/tests/all.rs @@ -68,9 +68,13 @@ macro_rules! bad_resp { } #[derive(RustcDecodable, Debug)] -struct Error { detail: String } +struct Error { + detail: String, +} #[derive(RustcDecodable)] -struct Bad { errors: Vec } +struct Bad { + errors: Vec, +} mod badge; mod category; @@ -139,7 +143,9 @@ fn ok_resp(r: &conduit::Response) -> bool { fn bad_resp(r: &mut conduit::Response) -> Option { let bad = json::(r); - if bad.errors.len() == 0 { return None } + if bad.errors.len() == 0 { + return None; + } Some(bad) } @@ -154,26 +160,24 @@ fn json(r: &mut conduit::Response) -> T { let j = fixup(j); let s = j.to_string(); return match json::decode(&s) { - Ok(t) => t, - Err(e) => panic!("failed to decode: {:?}\n{}", e, s), - }; + Ok(t) => t, + Err(e) => panic!("failed to decode: {:?}\n{}", e, s), + }; fn fixup(json: Json) -> Json { match json { Json::Object(object) => { - Json::Object(object.into_iter().map(|(k, v)| { - let k = if k == "crate" { - "krate".to_string() - } else { - k - }; - (k, fixup(v)) - }).collect()) - } - Json::Array(list) => { - Json::Array(list.into_iter().map(fixup).collect()) + Json::Object(object + .into_iter() + .map(|(k, v)| { + let k = + if k == "crate" { "krate".to_string() } else { k }; + (k, fixup(v)) + }) + .collect()) } + Json::Array(list) => Json::Array(list.into_iter().map(fixup).collect()), j => j, } } @@ -288,12 +292,13 @@ impl<'a> CrateBuilder<'a> { } if self.versions.is_empty() { - self.versions.push("0.99.0".parse().expect("invalid version number")); + self.versions + .push("0.99.0".parse().expect("invalid version number")); } for version_num in &self.versions { NewVersion::new(krate.id, version_num, &HashMap::new())? - .save(connection, &[])?; + .save(connection, &[])?; } if !self.keywords.is_empty() { @@ -307,8 +312,8 @@ impl<'a> CrateBuilder<'a> { let name = self.krate.name; self.build(connection) .unwrap_or_else(|e| { - panic!("Unable to create crate {}: {:?}", name, e); - }) + panic!("Unable to create crate {}: {:?}", name, e); + }) } } @@ -341,7 +346,8 @@ fn mock_user(req: &mut Request, u: User) -> User { u.email.as_ref().map(|s| &s[..]), u.name.as_ref().map(|s| &s[..]), u.gh_avatar.as_ref().map(|s| &s[..]), - &u.gh_access_token).unwrap(); + &u.gh_access_token) + .unwrap(); sign_in_as(req, &u); return u; } @@ -360,18 +366,20 @@ fn mock_crate(req: &mut Request, krate: Crate) -> (Crate, Version) { mock_crate_vers(req, krate, &semver::Version::parse("1.0.0").unwrap()) } -fn mock_crate_vers(req: &mut Request, krate: Crate, v: &semver::Version) - -> (Crate, Version) { +fn mock_crate_vers(req: &mut Request, krate: Crate, v: &semver::Version) -> (Crate, Version) { let user = req.extensions().find::().unwrap(); - let mut krate = Crate::find_or_insert(req.tx().unwrap(), &krate.name, - user.id, &krate.description, + let mut krate = Crate::find_or_insert(req.tx().unwrap(), + &krate.name, + user.id, + &krate.description, &krate.homepage, &krate.documentation, &krate.readme, &krate.repository, &krate.license, &None, - krate.max_upload_size).unwrap(); + krate.max_upload_size) + .unwrap(); let v = krate.add_version(req.tx().unwrap(), v, &HashMap::new(), &[]); (krate, v.unwrap()) } @@ -387,22 +395,35 @@ fn new_dependency(conn: &PgConnection, version: &Version, krate: &Crate) -> Depe optional: false, ..Default::default() }; - insert(&dep).into(dependencies::table).get_result(conn).unwrap() + insert(&dep) + .into(dependencies::table) + .get_result(conn) + .unwrap() } -fn mock_dep(req: &mut Request, version: &Version, krate: &Crate, - target: Option<&str>) -> Dependency { +fn mock_dep(req: &mut Request, + version: &Version, + krate: &Crate, + target: Option<&str>) + -> Dependency { Dependency::insert(req.tx().unwrap(), version.id, krate.id, &semver::VersionReq::parse(">= 0").unwrap(), Kind::Normal, - false, true, &[], - &target.map(|s| s.to_string())).unwrap() + false, + true, + &[], + &target.map(|s| s.to_string())) + .unwrap() } fn new_category<'a>(category: &'a str, slug: &'a str) -> NewCategory<'a> { - NewCategory { category: category, slug: slug, ..NewCategory::default() } + NewCategory { + category: category, + slug: slug, + ..NewCategory::default() + } } fn mock_category(req: &mut Request, name: &str, slug: &str) -> Category { @@ -410,7 +431,8 @@ fn mock_category(req: &mut Request, name: &str, slug: &str) -> Category { let stmt = conn.prepare(" \ INSERT INTO categories (category, slug) \ VALUES ($1, $2) \ - RETURNING *").unwrap(); + RETURNING *") + .unwrap(); let rows = stmt.query(&[&name, &slug]).unwrap(); Model::from_row(&rows.iter().next().unwrap()) } @@ -419,11 +441,7 @@ fn logout(req: &mut Request) { req.mut_extensions().pop::(); } -fn request_with_user_and_mock_crate( - app: &Arc, - user: NewUser, - krate: &str, -) -> MockRequest { +fn request_with_user_and_mock_crate(app: &Arc, user: NewUser, krate: &str) -> MockRequest { let mut req = new_req(app.clone(), krate, "1.0.0"); { let conn = app.diesel_database.get().unwrap(); @@ -438,89 +456,98 @@ fn new_req(app: Arc, krate: &str, version: &str) -> MockRequest { new_req_full(app, ::krate(krate), version, Vec::new()) } -fn new_req_full(app: Arc, krate: Crate, version: &str, - deps: Vec) -> MockRequest { +fn new_req_full(app: Arc, + krate: Crate, + version: &str, + deps: Vec) + -> MockRequest { let mut req = ::req(app, Method::Put, "/api/v1/crates/new"); - req.with_body(&new_req_body( - krate, version, deps, Vec::new(), Vec::new(), HashMap::new() - )); + req.with_body(&new_req_body(krate, version, deps, Vec::new(), Vec::new(), HashMap::new())); return req; } -fn new_req_with_keywords(app: Arc, krate: Crate, version: &str, - kws: Vec) -> MockRequest { +fn new_req_with_keywords(app: Arc, + krate: Crate, + version: &str, + kws: Vec) + -> MockRequest { let mut req = ::req(app, Method::Put, "/api/v1/crates/new"); - req.with_body(&new_req_body( - krate, version, Vec::new(), kws, Vec::new(), HashMap::new() - )); + req.with_body(&new_req_body(krate, version, Vec::new(), kws, Vec::new(), HashMap::new())); return req; } -fn new_req_with_categories(app: Arc, krate: Crate, version: &str, - cats: Vec) -> MockRequest { +fn new_req_with_categories(app: Arc, + krate: Crate, + version: &str, + cats: Vec) + -> MockRequest { let mut req = ::req(app, Method::Put, "/api/v1/crates/new"); - req.with_body(&new_req_body( - krate, version, Vec::new(), Vec::new(), cats, HashMap::new() - )); + req.with_body(&new_req_body(krate, version, Vec::new(), Vec::new(), cats, HashMap::new())); return req; } -fn new_req_with_badges(app: Arc, krate: Crate, version: &str, +fn new_req_with_badges(app: Arc, + krate: Crate, + version: &str, badges: HashMap>) -> MockRequest { let mut req = ::req(app, Method::Put, "/api/v1/crates/new"); - req.with_body(&new_req_body( - krate, version, Vec::new(), Vec::new(), Vec::new(), badges - )); + req.with_body(&new_req_body(krate, version, Vec::new(), Vec::new(), Vec::new(), badges)); return req; } fn new_req_body_version_2(krate: Crate) -> Vec { - new_req_body( - krate, "2.0.0", Vec::new(), Vec::new(), Vec::new(), HashMap::new() - ) -} - -fn new_req_body(krate: Crate, version: &str, deps: Vec, - kws: Vec, cats: Vec, - badges: HashMap>) -> Vec { + new_req_body(krate, + "2.0.0", + Vec::new(), + Vec::new(), + Vec::new(), + HashMap::new()) +} + +fn new_req_body(krate: Crate, + version: &str, + deps: Vec, + kws: Vec, + cats: Vec, + badges: HashMap>) + -> Vec { let kws = kws.into_iter().map(u::Keyword).collect(); let cats = cats.into_iter().map(u::Category).collect(); new_crate_to_body(&u::NewCrate { - name: u::CrateName(krate.name), - vers: u::CrateVersion(semver::Version::parse(version).unwrap()), - features: HashMap::new(), - deps: deps, - authors: vec!["foo".to_string()], - description: Some("description".to_string()), - homepage: krate.homepage, - documentation: krate.documentation, - readme: krate.readme, - keywords: Some(u::KeywordList(kws)), - categories: Some(u::CategoryList(cats)), - license: Some("MIT".to_string()), - license_file: None, - repository: krate.repository, - badges: Some(badges), - }, &[]) + name: u::CrateName(krate.name), + vers: u::CrateVersion(semver::Version::parse(version).unwrap()), + features: HashMap::new(), + deps: deps, + authors: vec!["foo".to_string()], + description: Some("description".to_string()), + homepage: krate.homepage, + documentation: krate.documentation, + readme: krate.readme, + keywords: Some(u::KeywordList(kws)), + categories: Some(u::CategoryList(cats)), + license: Some("MIT".to_string()), + license_file: None, + repository: krate.repository, + badges: Some(badges), + }, + &[]) } fn new_crate_to_body(new_crate: &u::NewCrate, krate: &[u8]) -> Vec { let json = json::encode(&new_crate).unwrap(); let mut body = Vec::new(); - body.extend([ - (json.len() >> 0) as u8, - (json.len() >> 8) as u8, - (json.len() >> 16) as u8, - (json.len() >> 24) as u8, - ].iter().cloned()); + body.extend([(json.len() >> 0) as u8, + (json.len() >> 8) as u8, + (json.len() >> 16) as u8, + (json.len() >> 24) as u8] + .iter() + .cloned()); body.extend(json.as_bytes().iter().cloned()); - body.extend(&[ - (krate.len() >> 0) as u8, - (krate.len() >> 8) as u8, - (krate.len() >> 16) as u8, - (krate.len() >> 24) as u8, - ]); + body.extend(&[(krate.len() >> 0) as u8, + (krate.len() >> 8) as u8, + (krate.len() >> 16) as u8, + (krate.len() >> 24) as u8]); body.extend(krate); body } diff --git a/src/tests/badge.rs b/src/tests/badge.rs index df997918390..d094e6fedd3 100644 --- a/src/tests/badge.rs +++ b/src/tests/badge.rs @@ -27,11 +27,8 @@ fn set_up() -> (Arc, Crate, BadgeRef) { let krate = { let conn = app.diesel_database.get().unwrap(); - let u = ::new_user("foo") - .create_or_update(&conn) - .unwrap(); - ::CrateBuilder::new("badged_crate", u.id) - .expect_build(&conn) + let u = ::new_user("foo").create_or_update(&conn).unwrap(); + ::CrateBuilder::new("badged_crate", u.id).expect_build(&conn) }; let appveyor = Badge::Appveyor { @@ -40,60 +37,36 @@ fn set_up() -> (Arc, Crate, BadgeRef) { repository: String::from("rust-lang/cargo"), }; let mut badge_attributes_appveyor = HashMap::new(); - badge_attributes_appveyor.insert( - String::from("service"), - String::from("github") - ); - badge_attributes_appveyor.insert( - String::from("repository"), - String::from("rust-lang/cargo") - ); + badge_attributes_appveyor.insert(String::from("service"), String::from("github")); + badge_attributes_appveyor.insert(String::from("repository"), String::from("rust-lang/cargo")); let travis_ci = Badge::TravisCi { branch: Some(String::from("beta")), repository: String::from("rust-lang/rust"), }; let mut badge_attributes_travis_ci = HashMap::new(); - badge_attributes_travis_ci.insert( - String::from("branch"), - String::from("beta") - ); - badge_attributes_travis_ci.insert( - String::from("repository"), - String::from("rust-lang/rust") - ); + badge_attributes_travis_ci.insert(String::from("branch"), String::from("beta")); + badge_attributes_travis_ci.insert(String::from("repository"), String::from("rust-lang/rust")); let gitlab = Badge::GitLab { branch: Some(String::from("beta")), repository: String::from("rust-lang/rust"), }; let mut badge_attributes_gitlab = HashMap::new(); - badge_attributes_gitlab.insert( - String::from("branch"), - String::from("beta") - ); - badge_attributes_gitlab.insert( - String::from("repository"), - String::from("rust-lang/rust") - ); - - let isitmaintained_issue_resolution = Badge::IsItMaintainedIssueResolution { - repository: String::from("rust-lang/rust"), - }; + badge_attributes_gitlab.insert(String::from("branch"), String::from("beta")); + badge_attributes_gitlab.insert(String::from("repository"), String::from("rust-lang/rust")); + + let isitmaintained_issue_resolution = + Badge::IsItMaintainedIssueResolution { repository: String::from("rust-lang/rust") }; let mut badge_attributes_isitmaintained_issue_resolution = HashMap::new(); - badge_attributes_isitmaintained_issue_resolution.insert( - String::from("repository"), - String::from("rust-lang/rust") - ); + badge_attributes_isitmaintained_issue_resolution + .insert(String::from("repository"), String::from("rust-lang/rust")); - let isitmaintained_open_issues = Badge::IsItMaintainedOpenIssues { - repository: String::from("rust-lang/rust"), - }; + let isitmaintained_open_issues = + Badge::IsItMaintainedOpenIssues { repository: String::from("rust-lang/rust") }; let mut badge_attributes_isitmaintained_open_issues = HashMap::new(); - badge_attributes_isitmaintained_open_issues.insert( - String::from("repository"), - String::from("rust-lang/rust") - ); + badge_attributes_isitmaintained_open_issues + .insert(String::from("repository"), String::from("rust-lang/rust")); let codecov = Badge::Codecov { service: Some(String::from("github")), @@ -101,18 +74,9 @@ fn set_up() -> (Arc, Crate, BadgeRef) { repository: String::from("rust-lang/rust"), }; let mut badge_attributes_codecov = HashMap::new(); - badge_attributes_codecov.insert( - String::from("branch"), - String::from("beta") - ); - badge_attributes_codecov.insert( - String::from("repository"), - String::from("rust-lang/rust") - ); - badge_attributes_codecov.insert( - String::from("service"), - String::from("github") - ); + badge_attributes_codecov.insert(String::from("branch"), String::from("beta")); + badge_attributes_codecov.insert(String::from("repository"), String::from("rust-lang/rust")); + badge_attributes_codecov.insert(String::from("service"), String::from("github")); let coveralls = Badge::Coveralls { service: Some(String::from("github")), @@ -120,18 +84,9 @@ fn set_up() -> (Arc, Crate, BadgeRef) { repository: String::from("rust-lang/rust"), }; let mut badge_attributes_coveralls = HashMap::new(); - badge_attributes_coveralls.insert( - String::from("branch"), - String::from("beta") - ); - badge_attributes_coveralls.insert( - String::from("repository"), - String::from("rust-lang/rust") - ); - badge_attributes_coveralls.insert( - String::from("service"), - String::from("github") - ); + badge_attributes_coveralls.insert(String::from("branch"), String::from("beta")); + badge_attributes_coveralls.insert(String::from("repository"), String::from("rust-lang/rust")); + badge_attributes_coveralls.insert(String::from("service"), String::from("github")); let badges = BadgeRef { appveyor: appveyor, @@ -141,7 +96,8 @@ fn set_up() -> (Arc, Crate, BadgeRef) { gitlab: gitlab, gitlab_attributes: badge_attributes_gitlab, isitmaintained_issue_resolution: isitmaintained_issue_resolution, - isitmaintained_issue_resolution_attributes: badge_attributes_isitmaintained_issue_resolution, + isitmaintained_issue_resolution_attributes: + badge_attributes_isitmaintained_issue_resolution, isitmaintained_open_issues: isitmaintained_open_issues, isitmaintained_open_issues_attributes: badge_attributes_isitmaintained_open_issues, codecov: codecov, @@ -170,10 +126,7 @@ fn update_add_appveyor() { let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); - badges.insert( - String::from("appveyor"), - test_badges.appveyor_attributes - ); + badges.insert(String::from("appveyor"), test_badges.appveyor_attributes); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.appveyor]); } @@ -185,10 +138,7 @@ fn update_add_travis_ci() { let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); - badges.insert( - String::from("travis-ci"), - test_badges.travis_ci_attributes - ); + badges.insert(String::from("travis-ci"), test_badges.travis_ci_attributes); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.travis_ci]); } @@ -200,10 +150,7 @@ fn update_add_gitlab() { let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); - badges.insert( - String::from("gitlab"), - test_badges.gitlab_attributes - ); + badges.insert(String::from("gitlab"), test_badges.gitlab_attributes); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.gitlab]); } @@ -215,12 +162,11 @@ fn update_add_isitmaintained_issue_resolution() { let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); - badges.insert( - String::from("is-it-maintained-issue-resolution"), - test_badges.isitmaintained_issue_resolution_attributes - ); + badges.insert(String::from("is-it-maintained-issue-resolution"), + test_badges.isitmaintained_issue_resolution_attributes); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); - assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.isitmaintained_issue_resolution]); + assert_eq!(krate.badges(&conn).unwrap(), + vec![test_badges.isitmaintained_issue_resolution]); } #[test] @@ -230,12 +176,11 @@ fn update_add_isitmaintained_open_issues() { let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); - badges.insert( - String::from("is-it-maintained-open-issues"), - test_badges.isitmaintained_open_issues_attributes - ); + badges.insert(String::from("is-it-maintained-open-issues"), + test_badges.isitmaintained_open_issues_attributes); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); - assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.isitmaintained_open_issues]); + assert_eq!(krate.badges(&conn).unwrap(), + vec![test_badges.isitmaintained_open_issues]); } #[test] @@ -245,10 +190,7 @@ fn update_add_codecov() { let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); - badges.insert( - String::from("codecov"), - test_badges.codecov_attributes - ); + badges.insert(String::from("codecov"), test_badges.codecov_attributes); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.codecov]); } @@ -260,10 +202,7 @@ fn update_add_coveralls() { let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); - badges.insert( - String::from("coveralls"), - test_badges.coveralls_attributes - ); + badges.insert(String::from("coveralls"), test_badges.coveralls_attributes); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.coveralls]); } @@ -276,19 +215,14 @@ fn replace_badge() { // Add a badge let mut badges = HashMap::new(); - badges.insert( - String::from("gitlab"), - test_badges.gitlab_attributes - ); + badges.insert(String::from("gitlab"), test_badges.gitlab_attributes); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.gitlab]); // Replace with another badge badges.clear(); - badges.insert( - String::from("travis-ci"), - test_badges.travis_ci_attributes.clone() - ); + badges.insert(String::from("travis-ci"), + test_badges.travis_ci_attributes.clone()); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.travis_ci]); } @@ -301,10 +235,7 @@ fn update_attributes() { // Add a travis-ci badge let mut badges = HashMap::new(); - badges.insert( - String::from("travis-ci"), - test_badges.travis_ci_attributes - ); + badges.insert(String::from("travis-ci"), test_badges.travis_ci_attributes); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); let current_badges = krate.badges(&conn).unwrap(); assert_eq!(current_badges.len(), 1); @@ -317,14 +248,9 @@ fn update_attributes() { repository: String::from("rust-lang/rust"), }; let mut badge_attributes_travis_ci2 = HashMap::new(); - badge_attributes_travis_ci2.insert( - String::from("repository"), - String::from("rust-lang/rust") - ); - badges.insert( - String::from("travis-ci"), - badge_attributes_travis_ci2.clone() - ); + badge_attributes_travis_ci2.insert(String::from("repository"), String::from("rust-lang/rust")); + badges.insert(String::from("travis-ci"), + badge_attributes_travis_ci2.clone()); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); let current_badges = krate.badges(&conn).unwrap(); assert_eq!(current_badges.len(), 1); @@ -340,18 +266,9 @@ fn clear_badges() { let mut badges = HashMap::new(); // Adding 3 badges - badges.insert( - String::from("appveyor"), - test_badges.appveyor_attributes - ); - badges.insert( - String::from("travis-ci"), - test_badges.travis_ci_attributes - ); - badges.insert( - String::from("gitlab"), - test_badges.gitlab_attributes - ); + badges.insert(String::from("appveyor"), test_badges.appveyor_attributes); + badges.insert(String::from("travis-ci"), test_badges.travis_ci_attributes); + badges.insert(String::from("gitlab"), test_badges.gitlab_attributes); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); let current_badges = krate.badges(&conn).unwrap(); @@ -376,14 +293,8 @@ fn appveyor_extra_keys() { // Extra invalid keys are fine, they just get ignored let mut appveyor_attributes = test_badges.appveyor_attributes.clone(); - appveyor_attributes.insert( - String::from("extra"), - String::from("info") - ); - badges.insert( - String::from("appveyor"), - test_badges.appveyor_attributes - ); + appveyor_attributes.insert(String::from("extra"), String::from("info")); + badges.insert(String::from("appveyor"), test_badges.appveyor_attributes); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.appveyor]); @@ -399,10 +310,7 @@ fn travis_ci_required_keys() { // Repository is a required key test_badges.travis_ci_attributes.remove("repository"); - badges.insert( - String::from("travis-ci"), - test_badges.travis_ci_attributes - ); + badges.insert(String::from("travis-ci"), test_badges.travis_ci_attributes); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); @@ -420,10 +328,7 @@ fn gitlab_required_keys() { // Repository is a required key test_badges.gitlab_attributes.remove("repository"); - badges.insert( - String::from("gitlab"), - test_badges.gitlab_attributes - ); + badges.insert(String::from("gitlab"), test_badges.gitlab_attributes); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); @@ -440,11 +345,11 @@ fn isitmaintained_issue_resolution_required_keys() { let mut badges = HashMap::new(); // Repository is a required key - test_badges.isitmaintained_issue_resolution_attributes.remove("repository"); - badges.insert( - String::from("isitmaintained_issue_resolution"), - test_badges.isitmaintained_issue_resolution_attributes - ); + test_badges + .isitmaintained_issue_resolution_attributes + .remove("repository"); + badges.insert(String::from("isitmaintained_issue_resolution"), + test_badges.isitmaintained_issue_resolution_attributes); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); @@ -461,11 +366,11 @@ fn isitmaintained_open_issues_required_keys() { let mut badges = HashMap::new(); // Repository is a required key - test_badges.isitmaintained_open_issues_attributes.remove("repository"); - badges.insert( - String::from("isitmaintained_open_issues"), - test_badges.isitmaintained_open_issues_attributes - ); + test_badges + .isitmaintained_open_issues_attributes + .remove("repository"); + badges.insert(String::from("isitmaintained_open_issues"), + test_badges.isitmaintained_open_issues_attributes); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); @@ -483,10 +388,7 @@ fn codecov_required_keys() { // Repository is a required key test_badges.codecov_attributes.remove("repository"); - badges.insert( - String::from("codecov"), - test_badges.codecov_attributes - ); + badges.insert(String::from("codecov"), test_badges.codecov_attributes); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); @@ -504,10 +406,7 @@ fn coveralls_required_keys() { // Repository is a required key test_badges.coveralls_attributes.remove("repository"); - badges.insert( - String::from("coveralls"), - test_badges.coveralls_attributes - ); + badges.insert(String::from("coveralls"), test_badges.coveralls_attributes); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); @@ -525,14 +424,9 @@ fn unknown_badge() { // This is not a badge that crates.io knows about let mut invalid_attributes = HashMap::new(); - invalid_attributes.insert( - String::from("not-a-badge-attribute"), - String::from("not-a-badge-value") - ); - badges.insert( - String::from("not-a-badge"), - invalid_attributes - ); + invalid_attributes.insert(String::from("not-a-badge-attribute"), + String::from("not-a-badge-value")); + badges.insert(String::from("not-a-badge"), invalid_attributes); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); diff --git a/src/tests/category.rs b/src/tests/category.rs index b1beb4a1f3b..9c30335fe20 100644 --- a/src/tests/category.rs +++ b/src/tests/category.rs @@ -5,14 +5,21 @@ use cargo_registry::db::RequestTransaction; use cargo_registry::category::{Category, EncodableCategory, EncodableCategoryWithSubcategories}; #[derive(RustcDecodable)] -struct CategoryList { categories: Vec, meta: CategoryMeta } +struct CategoryList { + categories: Vec, + meta: CategoryMeta, +} #[derive(RustcDecodable)] -struct CategoryMeta { total: i32 } +struct CategoryMeta { + total: i32, +} #[derive(RustcDecodable)] -struct GoodCategory { category: EncodableCategory } +struct GoodCategory { + category: EncodableCategory, +} #[derive(RustcDecodable)] struct CategoryWithSubcategories { - category: EncodableCategoryWithSubcategories + category: EncodableCategoryWithSubcategories, } #[test] @@ -86,9 +93,7 @@ fn update_crate() { assert_eq!(cnt(&mut req, "category-2"), 0); // Replacing one category with another - Category::update_crate_old( - req.tx().unwrap(), &krate, &["category-2".to_string()] - ).unwrap(); + Category::update_crate_old(req.tx().unwrap(), &krate, &["category-2".to_string()]).unwrap(); assert_eq!(cnt(&mut req, "cat1"), 0); assert_eq!(cnt(&mut req, "category-2"), 1); @@ -98,9 +103,10 @@ fn update_crate() { assert_eq!(cnt(&mut req, "category-2"), 0); // Adding 2 categories - Category::update_crate_old( - req.tx().unwrap(), &krate, &["cat1".to_string(), - "category-2".to_string()]).unwrap(); + Category::update_crate_old(req.tx().unwrap(), + &krate, + &["cat1".to_string(), "category-2".to_string()]) + .unwrap(); assert_eq!(cnt(&mut req, "cat1"), 1); assert_eq!(cnt(&mut req, "category-2"), 1); @@ -110,10 +116,11 @@ fn update_crate() { assert_eq!(cnt(&mut req, "category-2"), 0); // Attempting to add one valid category and one invalid category - let invalid_categories = Category::update_crate_old( - req.tx().unwrap(), &krate, &["cat1".to_string(), - "catnope".to_string()] - ).unwrap(); + let invalid_categories = Category::update_crate_old(req.tx().unwrap(), + &krate, + &["cat1".to_string(), + "catnope".to_string()]) + .unwrap(); assert_eq!(invalid_categories, vec!["catnope".to_string()]); assert_eq!(cnt(&mut req, "cat1"), 1); assert_eq!(cnt(&mut req, "category-2"), 0); @@ -127,17 +134,16 @@ fn update_crate() { assert_eq!(json.meta.total, 2); // Attempting to add a category by display text; must use slug - Category::update_crate_old( - req.tx().unwrap(), &krate, &["Category 2".to_string()] - ).unwrap(); + Category::update_crate_old(req.tx().unwrap(), &krate, &["Category 2".to_string()]).unwrap(); assert_eq!(cnt(&mut req, "cat1"), 0); assert_eq!(cnt(&mut req, "category-2"), 0); // Add a category and its subcategory ::mock_category(&mut req, "cat1::bar", "cat1::bar"); - Category::update_crate_old( - req.tx().unwrap(), &krate, &["cat1".to_string(), - "cat1::bar".to_string()]).unwrap(); + Category::update_crate_old(req.tx().unwrap(), + &krate, + &["cat1".to_string(), "cat1::bar".to_string()]) + .unwrap(); assert_eq!(cnt(&mut req, "cat1"), 1); assert_eq!(cnt(&mut req, "cat1::bar"), 1); assert_eq!(cnt(&mut req, "category-2"), 0); diff --git a/src/tests/git.rs b/src/tests/git.rs index feac51e3177..bd2309fd66d 100644 --- a/src/tests/git.rs +++ b/src/tests/git.rs @@ -8,20 +8,25 @@ use git2; use url::Url; fn root() -> PathBuf { - env::current_dir().unwrap().join("tmp").join(thread::current().name().unwrap()) + env::current_dir() + .unwrap() + .join("tmp") + .join(thread::current().name().unwrap()) } -pub fn checkout() -> PathBuf { root().join("checkout") } -pub fn bare() -> PathBuf { root().join("bare") } +pub fn checkout() -> PathBuf { + root().join("checkout") +} +pub fn bare() -> PathBuf { + root().join("bare") +} pub fn init() { static INIT: Once = ONCE_INIT; let _ = fs::remove_dir_all(&checkout()); let _ = fs::remove_dir_all(&bare()); - INIT.call_once(|| { - fs::create_dir_all(root().parent().unwrap()).unwrap(); - }); + INIT.call_once(|| { fs::create_dir_all(root().parent().unwrap()).unwrap(); }); // Prepare a bare remote repo { @@ -38,7 +43,9 @@ pub fn init() { // Setup the `origin` remote checkout.remote_set_url("origin", &url).unwrap(); checkout.remote_set_pushurl("origin", Some(&url)).unwrap(); - checkout.remote_add_push("origin", "refs/heads/master").unwrap(); + checkout + .remote_add_push("origin", "refs/heads/master") + .unwrap(); // Create an empty initial commit let mut config = checkout.config().unwrap(); @@ -48,9 +55,9 @@ pub fn init() { let id = index.write_tree().unwrap(); let tree = checkout.find_tree(id).unwrap(); let sig = checkout.signature().unwrap(); - checkout.commit(Some("HEAD"), &sig, &sig, - "Initial Commit", - &tree, &[]).unwrap(); + checkout + .commit(Some("HEAD"), &sig, &sig, "Initial Commit", &tree, &[]) + .unwrap(); // Push the commit to the remote repo let mut origin = checkout.find_remote("origin").unwrap(); diff --git a/src/tests/keyword.rs b/src/tests/keyword.rs index 8d78f89f049..980615800d9 100644 --- a/src/tests/keyword.rs +++ b/src/tests/keyword.rs @@ -4,11 +4,18 @@ use conduit_test::MockRequest; use cargo_registry::keyword::{Keyword, EncodableKeyword}; #[derive(RustcDecodable)] -struct KeywordList { keywords: Vec, meta: KeywordMeta } +struct KeywordList { + keywords: Vec, + meta: KeywordMeta, +} #[derive(RustcDecodable)] -struct KeywordMeta { total: i32 } +struct KeywordMeta { + total: i32, +} #[derive(RustcDecodable)] -struct GoodKeyword { keyword: EncodableKeyword } +struct GoodKeyword { + keyword: EncodableKeyword, +} #[test] fn index() { @@ -72,12 +79,9 @@ fn update_crate() { let krate = { let conn = app.diesel_database.get().unwrap(); - let u = ::new_user("foo") - .create_or_update(&conn) - .unwrap(); + let u = ::new_user("foo").create_or_update(&conn).unwrap(); Keyword::find_or_create_all(&conn, &["kw1", "kw2"]).unwrap(); - ::CrateBuilder::new("fookey", u.id) - .expect_build(&conn) + ::CrateBuilder::new("fookey", u.id).expect_build(&conn) }; { diff --git a/src/tests/krate.rs b/src/tests/krate.rs index 98f2838bd2f..2b10afc33a1 100644 --- a/src/tests/krate.rs +++ b/src/tests/krate.rs @@ -20,23 +20,47 @@ use cargo_registry::version::EncodableVersion; use cargo_registry::category::Category; #[derive(RustcDecodable)] -struct CrateList { crates: Vec, meta: CrateMeta } +struct CrateList { + crates: Vec, + meta: CrateMeta, +} #[derive(RustcDecodable)] -struct VersionsList { versions: Vec } +struct VersionsList { + versions: Vec, +} #[derive(RustcDecodable)] -struct CrateMeta { total: i32 } +struct CrateMeta { + total: i32, +} #[derive(RustcDecodable)] -struct Warnings { invalid_categories: Vec, invalid_badges: Vec } +struct Warnings { + invalid_categories: Vec, + invalid_badges: Vec, +} #[derive(RustcDecodable)] -struct GoodCrate { krate: EncodableCrate, warnings: Warnings } +struct GoodCrate { + krate: EncodableCrate, + warnings: Warnings, +} #[derive(RustcDecodable)] -struct CrateResponse { krate: EncodableCrate, versions: Vec, keywords: Vec } +struct CrateResponse { + krate: EncodableCrate, + versions: Vec, + keywords: Vec, +} #[derive(RustcDecodable)] -struct Deps { dependencies: Vec } +struct Deps { + dependencies: Vec, +} #[derive(RustcDecodable)] -struct RevDeps { dependencies: Vec, meta: CrateMeta } +struct RevDeps { + dependencies: Vec, + meta: CrateMeta, +} #[derive(RustcDecodable)] -struct Downloads { version_downloads: Vec } +struct Downloads { + version_downloads: Vec, +} fn new_crate(name: &str) -> u::NewCrate { u::NewCrate { @@ -69,11 +93,8 @@ fn index() { let krate = { let conn = app.diesel_database.get().unwrap(); - let u = ::new_user("foo") - .create_or_update(&conn) - .unwrap(); - ::CrateBuilder::new("fooindex", u.id) - .expect_build(&conn) + let u = ::new_user("foo").create_or_update(&conn).unwrap(); + ::CrateBuilder::new("fooindex", u.id).expect_build(&conn) }; let mut response = ok_resp!(middle.call(&mut req)); @@ -93,9 +114,7 @@ fn index_queries() { let krate2; { let conn = app.diesel_database.get().unwrap(); - u = ::new_user("foo") - .create_or_update(&conn) - .unwrap(); + u = ::new_user("foo").create_or_update(&conn).unwrap(); krate = ::CrateBuilder::new("foo_index_queries", u.id) .readme("readme") @@ -155,8 +174,12 @@ fn index_queries() { { let conn = app.diesel_database.get().unwrap(); - ::new_category("Category 1", "cat1").find_or_create(&conn).unwrap(); - ::new_category("Category 1::Ba'r", "cat1::bar").find_or_create(&conn).unwrap(); + ::new_category("Category 1", "cat1") + .find_or_create(&conn) + .unwrap(); + ::new_category("Category 1::Ba'r", "cat1::bar") + .find_or_create(&conn) + .unwrap(); Category::update_crate(&conn, &krate, &["cat1"]).unwrap(); Category::update_crate(&conn, &krate2, &["cat1::bar"]).unwrap(); } @@ -335,7 +358,8 @@ fn show() { assert_eq!(json.versions[0].num, "1.0.0"); let suffix = "/api/v1/crates/foo_show/1.0.0/download"; assert!(json.versions[0].dl_path.ends_with(suffix), - "bad suffix {}", json.versions[0].dl_path); + "bad suffix {}", + json.versions[0].dl_path); assert_eq!(1, json.keywords.len()); assert_eq!("kw1", json.keywords[0].id); @@ -395,7 +419,8 @@ fn new_bad_names() { ::mock_user(&mut req, ::user("foo")); let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("invalid crate name"), - "{:?}", json.errors); + "{:?}", + json.errors); } bad_name(""); @@ -421,7 +446,9 @@ fn new_krate_with_reserved_name() { let mut req = ::new_req(app, name, "1.0.0"); ::mock_user(&mut req, ::user("foo")); let json = bad_resp!(middle.call(&mut req)); - assert!(json.errors[0].detail.contains("cannot upload a crate with a reserved name")); + assert!(json.errors[0] + .detail + .contains("cannot upload a crate with a reserved name")); } test_bad_name("std"); @@ -468,7 +495,10 @@ fn new_krate_with_dependency() { let path = ::git::checkout().join("ne/w_/new_dep"); assert!(path.exists()); let mut contents = String::new(); - File::open(&path).unwrap().read_to_string(&mut contents).unwrap(); + File::open(&path) + .unwrap() + .read_to_string(&mut contents) + .unwrap(); let p: git::Crate = json::decode(&contents).unwrap(); assert_eq!(p.name, "new_dep"); assert_eq!(p.vers, "1.0.0"); @@ -479,17 +509,15 @@ fn new_krate_with_dependency() { #[test] fn new_krate_non_canon_crate_name_dependencies() { let (_b, app, middle) = ::app(); - let deps = vec![ - u::CrateDependency { - name: u::CrateName("foo-dep".to_string()), - optional: false, - default_features: true, - features: Vec::new(), - version_req: u::CrateVersionReq(semver::VersionReq::parse(">= 0").unwrap()), - target: None, - kind: None, - }, - ]; + let deps = vec![u::CrateDependency { + name: u::CrateName("foo-dep".to_string()), + optional: false, + default_features: true, + features: Vec::new(), + version_req: u::CrateVersionReq(semver::VersionReq::parse(">= 0").unwrap()), + target: None, + kind: None, + }]; let mut req = ::new_req_full(app.clone(), ::krate("new_dep"), "1.0.0", deps); { let conn = app.diesel_database.get().unwrap(); @@ -523,7 +551,9 @@ fn new_krate_with_wildcard_dependency() { ::CrateBuilder::new("foo_wild", user.id).expect_build(&conn); } let json = bad_resp!(middle.call(&mut req)); - assert!(json.errors[0].detail.contains("dependency constraints"), "{:?}", json.errors); + assert!(json.errors[0].detail.contains("dependency constraints"), + "{:?}", + json.errors); } #[test] @@ -563,7 +593,8 @@ fn new_krate_wrong_user() { let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("another user"), - "{:?}", json.errors); + "{:?}", + json.errors); } #[test] @@ -575,20 +606,25 @@ fn new_krate_bad_name() { ::sign_in(&mut req, &app); let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("invalid crate name"), - "{:?}", json.errors); + "{:?}", + json.errors); } { let mut req = ::new_req(app.clone(), "áccênts", "2.0.0"); ::sign_in(&mut req, &app); let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("invalid crate name"), - "{:?}", json.errors); + "{:?}", + json.errors); } } #[test] fn new_crate_owner() { - #[derive(RustcDecodable)] struct O { ok: bool } + #[derive(RustcDecodable)] + struct O { + ok: bool, + } let (_b, app, middle) = ::app(); @@ -606,26 +642,26 @@ fn new_crate_owner() { // Flag the second user as an owner let body = r#"{"users":["bar"]}"#; let mut response = ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_owner/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); assert!(::json::(&mut response).ok); bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_owner/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); // Make sure this shows up as one of their crates. let query = format!("user_id={}", u2.id); let mut response = ok_resp!(middle.call(req.with_path("/api/v1/crates") - .with_method(Method::Get) - .with_query(&query))); + .with_method(Method::Get) + .with_query(&query))); assert_eq!(::json::(&mut response).crates.len(), 1); // And upload a new crate as the first user let body = ::new_req_body_version_2(::krate("foo_owner")); ::sign_in_as(&mut req, &u2); let mut response = ok_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_method(Method::Put) - .with_body(&body))); + .with_method(Method::Put) + .with_body(&body))); ::json::(&mut response); } @@ -679,7 +715,8 @@ fn new_krate_duplicate_version() { } let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("already uploaded"), - "{:?}", json.errors); + "{:?}", + json.errors); } #[test] @@ -694,7 +731,8 @@ fn new_crate_similar_name() { } let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("previously named"), - "{:?}", json.errors); + "{:?}", + json.errors); } #[test] @@ -709,7 +747,8 @@ fn new_crate_similar_name_hyphen() { } let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("previously named"), - "{:?}", json.errors); + "{:?}", + json.errors); } #[test] @@ -724,7 +763,8 @@ fn new_crate_similar_name_underscore() { } let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("previously named"), - "{:?}", json.errors); + "{:?}", + json.errors); } #[test] @@ -738,7 +778,10 @@ fn new_krate_git_upload() { let path = ::git::checkout().join("3/f/fgt"); assert!(path.exists()); let mut contents = String::new(); - File::open(&path).unwrap().read_to_string(&mut contents).unwrap(); + File::open(&path) + .unwrap() + .read_to_string(&mut contents) + .unwrap(); let p: git::Crate = json::decode(&contents).unwrap(); assert_eq!(p.name, "fgt"); assert_eq!(p.vers, "1.0.0"); @@ -752,9 +795,11 @@ fn new_krate_git_upload_appends() { let (_b, app, middle) = ::app(); let path = ::git::checkout().join("3/f/fpp"); fs::create_dir_all(path.parent().unwrap()).unwrap(); - File::create(&path).unwrap().write_all( - br#"{"name":"FPP","vers":"0.0.1","deps":[],"features":{},"cksum":"3j3"} -"#).unwrap(); + File::create(&path) + .unwrap() + .write_all(br#"{"name":"FPP","vers":"0.0.1","deps":[],"features":{},"cksum":"3j3"} +"#) + .unwrap(); let mut req = ::new_req(app.clone(), "FPP", "1.0.0"); ::sign_in(&mut req, &app); @@ -762,7 +807,10 @@ fn new_krate_git_upload_appends() { ::json::(&mut response); let mut contents = String::new(); - File::open(&path).unwrap().read_to_string(&mut contents).unwrap(); + File::open(&path) + .unwrap() + .read_to_string(&mut contents) + .unwrap(); let mut lines = contents.lines(); let p1: git::Crate = json::decode(lines.next().unwrap().trim()).unwrap(); let p2: git::Crate = json::decode(lines.next().unwrap().trim()).unwrap(); @@ -785,8 +833,8 @@ fn new_krate_git_upload_with_conflicts() { let sig = repo.signature().unwrap(); let parent = repo.find_commit(target).unwrap(); let tree = repo.find_tree(parent.tree_id()).unwrap(); - repo.commit(Some("HEAD"), &sig, &sig, "empty commit", &tree, - &[&parent]).unwrap(); + repo.commit(Some("HEAD"), &sig, &sig, "empty commit", &tree, &[&parent]) + .unwrap(); } let mut req = ::new_req(app.clone(), "foo_conflicts", "1.0.0"); @@ -811,7 +859,8 @@ fn new_krate_dependency_missing() { ::sign_in(&mut req, &app); let mut response = ok_resp!(middle.call(&mut req)); let json = ::json::<::Bad>(&mut response); - assert!(json.errors[0].detail + assert!(json.errors[0] + .detail .contains("no known crate named `bar_missing`")); } @@ -824,9 +873,11 @@ fn summary_doesnt_die() { #[test] fn download() { - use ::time::{Duration, now_utc, strftime}; + use time::{Duration, now_utc, strftime}; let (_b, app, middle) = ::app(); - let mut req = ::req(app.clone(), Method::Get, "/api/v1/crates/foo_download/1.0.0/download"); + let mut req = ::req(app.clone(), + Method::Get, + "/api/v1/crates/foo_download/1.0.0/download"); { let conn = app.diesel_database.get().unwrap(); let user = ::new_user("foo").create_or_update(&conn).unwrap(); @@ -888,12 +939,13 @@ fn download() { #[test] fn download_bad() { let (_b, app, middle) = ::app(); - let mut req = ::req(app.clone(), Method::Get, "/api/v1/crates/foo_bad/0.1.0/download"); + let mut req = ::req(app.clone(), + Method::Get, + "/api/v1/crates/foo_bad/0.1.0/download"); { let conn = app.diesel_database.get().unwrap(); let user = ::new_user("foo").create_or_update(&conn).unwrap(); - ::CrateBuilder::new("foo_bad", user.id) - .expect_build(&conn); + ::CrateBuilder::new("foo_bad", user.id).expect_build(&conn); } let response = t_resp!(middle.call(&mut req)); assert_eq!(404, response.status.0) @@ -903,15 +955,15 @@ fn download_bad() { fn dependencies() { let (_b, app, middle) = ::app(); - let mut req = ::req(app.clone(), Method::Get, "/api/v1/crates/foo_deps/1.0.0/dependencies"); + let mut req = ::req(app.clone(), + Method::Get, + "/api/v1/crates/foo_deps/1.0.0/dependencies"); { let conn = app.diesel_database.get().unwrap(); let user = ::new_user("foo").create_or_update(&conn).unwrap(); - let c1 = ::CrateBuilder::new("foo_deps", user.id) - .expect_build(&conn); + let c1 = ::CrateBuilder::new("foo_deps", user.id).expect_build(&conn); let v = ::new_version(c1.id, "1.0.0").save(&conn, &[]).unwrap(); - let c2 = ::CrateBuilder::new("bar_deps", user.id) - .expect_build(&conn); + let c2 = ::CrateBuilder::new("bar_deps", user.id).expect_build(&conn); ::new_dependency(&conn, &v, &c2); } @@ -927,7 +979,9 @@ fn dependencies() { #[test] fn diesel_not_found_results_in_404() { let (_b, app, middle) = ::app(); - let mut req = ::req(app.clone(), Method::Get, "/api/v1/crates/foo_following/following"); + let mut req = ::req(app.clone(), + Method::Get, + "/api/v1/crates/foo_following/following"); { let conn = app.diesel_database.get().unwrap(); @@ -941,11 +995,19 @@ fn diesel_not_found_results_in_404() { #[test] fn following() { - #[derive(RustcDecodable)] struct F { following: bool } - #[derive(RustcDecodable)] struct O { ok: bool } + #[derive(RustcDecodable)] + struct F { + following: bool, + } + #[derive(RustcDecodable)] + struct O { + ok: bool, + } let (_b, app, middle) = ::app(); - let mut req = ::req(app.clone(), Method::Get, "/api/v1/crates/foo_following/following"); + let mut req = ::req(app.clone(), + Method::Get, + "/api/v1/crates/foo_following/following"); let user; { @@ -959,14 +1021,14 @@ fn following() { assert!(!::json::(&mut response).following); req.with_path("/api/v1/crates/foo_following/follow") - .with_method(Method::Put); + .with_method(Method::Put); let mut response = ok_resp!(middle.call(&mut req)); assert!(::json::(&mut response).ok); let mut response = ok_resp!(middle.call(&mut req)); assert!(::json::(&mut response).ok); req.with_path("/api/v1/crates/foo_following/following") - .with_method(Method::Get); + .with_method(Method::Get); let mut response = ok_resp!(middle.call(&mut req)); assert!(::json::(&mut response).following); @@ -978,28 +1040,34 @@ fn following() { assert_eq!(l.crates.len(), 1); req.with_path("/api/v1/crates/foo_following/follow") - .with_method(Method::Delete); + .with_method(Method::Delete); let mut response = ok_resp!(middle.call(&mut req)); assert!(::json::(&mut response).ok); let mut response = ok_resp!(middle.call(&mut req)); assert!(::json::(&mut response).ok); req.with_path("/api/v1/crates/foo_following/following") - .with_method(Method::Get); + .with_method(Method::Get); let mut response = ok_resp!(middle.call(&mut req)); assert!(!::json::(&mut response).following); req.with_path("/api/v1/crates") - .with_query("following=1") - .with_method(Method::Get); + .with_query("following=1") + .with_method(Method::Get); let mut response = ok_resp!(middle.call(&mut req)); assert_eq!(::json::(&mut response).crates.len(), 0); } #[test] fn owners() { - #[derive(RustcDecodable)] struct R { users: Vec } - #[derive(RustcDecodable)] struct O { ok: bool } + #[derive(RustcDecodable)] + struct R { + users: Vec, + } + #[derive(RustcDecodable)] + struct O { + ok: bool, + } let (_b, app, middle) = ::app(); let mut req = ::req(app.clone(), Method::Get, "/api/v1/crates/foo_owners/owners"); @@ -1021,7 +1089,7 @@ fn owners() { let body = r#"{"users":["foobar"]}"#; let mut response = ok_resp!(middle.call(req.with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_body(body.as_bytes()))); assert!(::json::(&mut response).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get))); @@ -1030,7 +1098,7 @@ fn owners() { let body = r#"{"users":["foobar"]}"#; let mut response = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_body(body.as_bytes()))); + .with_body(body.as_bytes()))); assert!(::json::(&mut response).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get))); @@ -1039,19 +1107,25 @@ fn owners() { let body = r#"{"users":["foo"]}"#; let mut response = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_body(body.as_bytes()))); + .with_body(body.as_bytes()))); ::json::<::Bad>(&mut response); let body = r#"{"users":["foobar"]}"#; let mut response = ok_resp!(middle.call(req.with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_body(body.as_bytes()))); assert!(::json::(&mut response).ok); } #[test] fn yank() { - #[derive(RustcDecodable)] struct O { ok: bool } - #[derive(RustcDecodable)] struct V { version: EncodableVersion } + #[derive(RustcDecodable)] + struct O { + ok: bool, + } + #[derive(RustcDecodable)] + struct V { + version: EncodableVersion, + } let (_b, app, middle) = ::app(); let path = ::git::checkout().join("3/f/fyk"); @@ -1061,44 +1135,53 @@ fn yank() { let mut response = ok_resp!(middle.call(&mut req)); ::json::(&mut response); let mut contents = String::new(); - File::open(&path).unwrap().read_to_string(&mut contents).unwrap(); + File::open(&path) + .unwrap() + .read_to_string(&mut contents) + .unwrap(); assert!(contents.contains("\"yanked\":false")); // make sure it's not yanked let mut r = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk/1.0.0"))); + .with_path("/api/v1/crates/fyk/1.0.0"))); assert!(!::json::(&mut r).version.yanked); // yank it let mut r = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_path("/api/v1/crates/fyk/1.0.0/yank"))); + .with_path("/api/v1/crates/fyk/1.0.0/yank"))); assert!(::json::(&mut r).ok); let mut contents = String::new(); - File::open(&path).unwrap().read_to_string(&mut contents).unwrap(); + File::open(&path) + .unwrap() + .read_to_string(&mut contents) + .unwrap(); assert!(contents.contains("\"yanked\":true")); let mut r = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk/1.0.0"))); + .with_path("/api/v1/crates/fyk/1.0.0"))); assert!(::json::(&mut r).version.yanked); // un-yank it let mut r = ok_resp!(middle.call(req.with_method(Method::Put) - .with_path("/api/v1/crates/fyk/1.0.0/unyank"))); + .with_path("/api/v1/crates/fyk/1.0.0/unyank"))); assert!(::json::(&mut r).ok); let mut contents = String::new(); - File::open(&path).unwrap().read_to_string(&mut contents).unwrap(); + File::open(&path) + .unwrap() + .read_to_string(&mut contents) + .unwrap(); assert!(contents.contains("\"yanked\":false")); let mut r = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk/1.0.0"))); + .with_path("/api/v1/crates/fyk/1.0.0"))); assert!(!::json::(&mut r).version.yanked); } #[test] fn yank_not_owner() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, ::new_user("bar"), "foo_not"); + let mut req = ::request_with_user_and_mock_crate(&app, ::new_user("bar"), "foo_not"); ::sign_in(&mut req, &app); - req.with_method(Method::Delete).with_path("/api/v1/crates/foo_not/1.0.0/yank"); + req.with_method(Method::Delete) + .with_path("/api/v1/crates/foo_not/1.0.0/yank"); let mut response = ok_resp!(middle.call(&mut req)); ::json::<::Bad>(&mut response); } @@ -1123,62 +1206,62 @@ fn yank_max_version() { // add version 2.0.0 let body = ::new_req_body_version_2(::krate("fyk_max")); let mut response = ok_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_method(Method::Put) - .with_body(&body))); + .with_method(Method::Put) + .with_body(&body))); let json: GoodCrate = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); // yank version 1.0.0 let mut r = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_path("/api/v1/crates/fyk_max/1.0.0/yank"))); + .with_path("/api/v1/crates/fyk_max/1.0.0/yank"))); assert!(::json::(&mut r).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + .with_path("/api/v1/crates/fyk_max"))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); // unyank version 1.0.0 let mut r = ok_resp!(middle.call(req.with_method(Method::Put) - .with_path("/api/v1/crates/fyk_max/1.0.0/unyank"))); + .with_path("/api/v1/crates/fyk_max/1.0.0/unyank"))); assert!(::json::(&mut r).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + .with_path("/api/v1/crates/fyk_max"))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); // yank version 2.0.0 let mut r = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_path("/api/v1/crates/fyk_max/2.0.0/yank"))); + .with_path("/api/v1/crates/fyk_max/2.0.0/yank"))); assert!(::json::(&mut r).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + .with_path("/api/v1/crates/fyk_max"))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "1.0.0"); // yank version 1.0.0 let mut r = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_path("/api/v1/crates/fyk_max/1.0.0/yank"))); + .with_path("/api/v1/crates/fyk_max/1.0.0/yank"))); assert!(::json::(&mut r).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + .with_path("/api/v1/crates/fyk_max"))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "0.0.0"); // unyank version 2.0.0 let mut r = ok_resp!(middle.call(req.with_method(Method::Put) - .with_path("/api/v1/crates/fyk_max/2.0.0/unyank"))); + .with_path("/api/v1/crates/fyk_max/2.0.0/unyank"))); assert!(::json::(&mut r).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + .with_path("/api/v1/crates/fyk_max"))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); // unyank version 1.0.0 let mut r = ok_resp!(middle.call(req.with_method(Method::Put) - .with_path("/api/v1/crates/fyk_max/1.0.0/unyank"))); + .with_path("/api/v1/crates/fyk_max/1.0.0/unyank"))); assert!(::json::(&mut r).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + .with_path("/api/v1/crates/fyk_max"))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); } @@ -1202,27 +1285,27 @@ fn publish_after_yank_max_version() { // yank version 1.0.0 let mut r = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_path("/api/v1/crates/fyk_max/1.0.0/yank"))); + .with_path("/api/v1/crates/fyk_max/1.0.0/yank"))); assert!(::json::(&mut r).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + .with_path("/api/v1/crates/fyk_max"))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "0.0.0"); // add version 2.0.0 let body = ::new_req_body_version_2(::krate("fyk_max")); let mut response = ok_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_method(Method::Put) - .with_body(&body))); + .with_method(Method::Put) + .with_body(&body))); let json: GoodCrate = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); // unyank version 1.0.0 let mut r = ok_resp!(middle.call(req.with_method(Method::Put) - .with_path("/api/v1/crates/fyk_max/1.0.0/unyank"))); + .with_path("/api/v1/crates/fyk_max/1.0.0/unyank"))); assert!(::json::(&mut r).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + .with_path("/api/v1/crates/fyk_max"))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); } @@ -1273,7 +1356,9 @@ fn good_categories() { ::sign_in(&mut req, &app); { let conn = app.diesel_database.get().unwrap(); - ::new_category("Category 1", "cat1").find_or_create(&conn).unwrap(); + ::new_category("Category 1", "cat1") + .find_or_create(&conn) + .unwrap(); } let mut response = ok_resp!(middle.call(&mut req)); let json: GoodCrate = ::json(&mut response); @@ -1301,10 +1386,8 @@ fn good_badges() { let krate = ::krate("foobadger"); let mut badges = HashMap::new(); let mut badge_attributes = HashMap::new(); - badge_attributes.insert( - String::from("repository"), - String::from("rust-lang/crates.io") - ); + badge_attributes.insert(String::from("repository"), + String::from("rust-lang/crates.io")); badges.insert(String::from("travis-ci"), badge_attributes); let (_b, app, middle) = ::app(); @@ -1316,19 +1399,16 @@ fn good_badges() { assert_eq!(json.krate.name, "foobadger"); assert_eq!(json.krate.max_version, "1.0.0"); - let mut response = ok_resp!( - middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/foobadger"))); + let mut response = ok_resp!(middle.call(req.with_method(Method::Get) + .with_path("/api/v1/crates/foobadger"))); let json: CrateResponse = ::json(&mut response); let badges = json.krate.badges.unwrap(); assert_eq!(badges.len(), 1); assert_eq!(badges[0].badge_type, "travis-ci"); - assert_eq!( - badges[0].attributes.get("repository").unwrap(), - &Some(String::from("rust-lang/crates.io")) - ); + assert_eq!(badges[0].attributes.get("repository").unwrap(), + &Some(String::from("rust-lang/crates.io"))); } #[test] @@ -1338,18 +1418,12 @@ fn ignored_badges() { // Known badge type, missing required repository attribute let mut badge_attributes = HashMap::new(); - badge_attributes.insert( - String::from("branch"), - String::from("master") - ); + badge_attributes.insert(String::from("branch"), String::from("master")); badges.insert(String::from("travis-ci"), badge_attributes); // Unknown badge type let mut unknown_badge_attributes = HashMap::new(); - unknown_badge_attributes.insert( - String::from("repository"), - String::from("rust-lang/rust") - ); + unknown_badge_attributes.insert(String::from("repository"), String::from("rust-lang/rust")); badges.insert(String::from("not-a-badge"), unknown_badge_attributes); let (_b, app, middle) = ::app(); @@ -1362,12 +1436,15 @@ fn ignored_badges() { assert_eq!(json.krate.name, "foo_ignored_badge"); assert_eq!(json.krate.max_version, "1.0.0"); assert_eq!(json.warnings.invalid_badges.len(), 2); - assert!(json.warnings.invalid_badges.contains(&"travis-ci".to_string())); - assert!(json.warnings.invalid_badges.contains(&"not-a-badge".to_string())); + assert!(json.warnings + .invalid_badges + .contains(&"travis-ci".to_string())); + assert!(json.warnings + .invalid_badges + .contains(&"not-a-badge".to_string())); - let mut response = ok_resp!( - middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/foo_ignored_badge"))); + let mut response = ok_resp!(middle.call(req.with_method(Method::Get) + .with_path("/api/v1/crates/foo_ignored_badge",))); let json: CrateResponse = ::json(&mut response); @@ -1381,8 +1458,7 @@ fn reverse_dependencies() { let v100 = semver::Version::parse("1.0.0").unwrap(); let v110 = semver::Version::parse("1.1.0").unwrap(); - let mut req = ::req(app, Method::Get, - "/api/v1/crates/c1/reverse_dependencies"); + let mut req = ::req(app, Method::Get, "/api/v1/crates/c1/reverse_dependencies"); ::mock_user(&mut req, ::user("foo")); let (c1, _) = ::mock_crate_vers(&mut req, ::krate("c1"), &v100); let (_, c2v1) = ::mock_crate_vers(&mut req, ::krate("c2"), &v100); @@ -1413,8 +1489,7 @@ fn reverse_dependencies_when_old_version_doesnt_depend_but_new_does() { let v100 = semver::Version::parse("1.0.0").unwrap(); let v110 = semver::Version::parse("1.1.0").unwrap(); let v200 = semver::Version::parse("2.0.0").unwrap(); - let mut req = ::req(app, Method::Get, - "/api/v1/crates/c1/reverse_dependencies"); + let mut req = ::req(app, Method::Get, "/api/v1/crates/c1/reverse_dependencies"); ::mock_user(&mut req, ::user("foo")); let (c1, _) = ::mock_crate_vers(&mut req, ::krate("c1"), &v110); let _ = ::mock_crate_vers(&mut req, ::krate("c2"), &v100); @@ -1435,8 +1510,7 @@ fn reverse_dependencies_when_old_version_depended_but_new_doesnt() { let v100 = semver::Version::parse("1.0.0").unwrap(); let v200 = semver::Version::parse("2.0.0").unwrap(); - let mut req = ::req(app, Method::Get, - "/api/v1/crates/c1/reverse_dependencies"); + let mut req = ::req(app, Method::Get, "/api/v1/crates/c1/reverse_dependencies"); ::mock_user(&mut req, ::user("foo")); let (c1, _) = ::mock_crate_vers(&mut req, ::krate("c1"), &v100); let (_, c2v1) = ::mock_crate_vers(&mut req, ::krate("c2"), &v100); @@ -1456,8 +1530,7 @@ fn prerelease_versions_not_included_in_reverse_dependencies() { let v100 = semver::Version::parse("1.0.0").unwrap(); let v110_pre = semver::Version::parse("1.1.0-pre").unwrap(); - let mut req = ::req(app, Method::Get, - "/api/v1/crates/c1/reverse_dependencies"); + let mut req = ::req(app, Method::Get, "/api/v1/crates/c1/reverse_dependencies"); ::mock_user(&mut req, ::user("foo")); let (c1, _) = ::mock_crate_vers(&mut req, ::krate("c1"), &v100); let _ = ::mock_crate_vers(&mut req, ::krate("c2"), &v110_pre); @@ -1479,8 +1552,7 @@ fn yanked_versions_not_included_in_reverse_dependencies() { let v100 = semver::Version::parse("1.0.0").unwrap(); let v200 = semver::Version::parse("2.0.0").unwrap(); - let mut req = ::req(app, Method::Get, - "/api/v1/crates/c1/reverse_dependencies"); + let mut req = ::req(app, Method::Get, "/api/v1/crates/c1/reverse_dependencies"); ::mock_user(&mut req, ::user("foo")); let (c1, _) = ::mock_crate_vers(&mut req, ::krate("c1"), &v100); let _ = ::mock_crate_vers(&mut req, ::krate("c2"), &v100); @@ -1517,7 +1589,8 @@ fn author_license_and_description_required() { assert!(json.errors[0].detail.contains("author") && json.errors[0].detail.contains("description") && json.errors[0].detail.contains("license"), - "{:?}", json.errors); + "{:?}", + json.errors); new_crate.license = Some("MIT".to_string()); new_crate.authors.push("".to_string()); @@ -1526,7 +1599,8 @@ fn author_license_and_description_required() { assert!(json.errors[0].detail.contains("author") && json.errors[0].detail.contains("description") && !json.errors[0].detail.contains("license"), - "{:?}", json.errors); + "{:?}", + json.errors); new_crate.license = None; new_crate.license_file = Some("foo".to_string()); @@ -1536,6 +1610,6 @@ fn author_license_and_description_required() { assert!(!json.errors[0].detail.contains("author") && json.errors[0].detail.contains("description") && !json.errors[0].detail.contains("license"), - "{:?}", json.errors); + "{:?}", + json.errors); } - diff --git a/src/tests/record.rs b/src/tests/record.rs index 2a29ee01614..cfe0d323867 100644 --- a/src/tests/record.rs +++ b/src/tests/record.rs @@ -37,7 +37,9 @@ impl Write for Sink { fn write(&mut self, data: &[u8]) -> io::Result { Write::write(&mut *self.0.lock().unwrap(), data) } - fn flush(&mut self) -> io::Result<()> { Ok(()) } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } } impl Drop for Bomb { @@ -45,12 +47,11 @@ impl Drop for Bomb { t!(self.quit.send(())); drop(TcpStream::connect(&t!(self.accept.local_addr()))); let res = self.rx.recv(); - let stderr = str::from_utf8(&self.iorx.0.lock().unwrap()).unwrap() - .to_string(); + let stderr = str::from_utf8(&self.iorx.0.lock().unwrap()) + .unwrap() + .to_string(); match res { - Err(..) if !thread::panicking() => { - panic!("server subtask failed: {}", stderr) - } + Err(..) if !thread::panicking() => panic!("server subtask failed: {}", stderr), _ => { if stderr.len() > 0 { println!("server subtask failed: {}", stderr) @@ -61,7 +62,11 @@ impl Drop for Bomb { } fn cache_file(name: &str) -> PathBuf { - PathBuf::from(file!()).parent().unwrap().join("http-data").join(name) + PathBuf::from(file!()) + .parent() + .unwrap() + .join("http-data") + .join(name) } pub fn proxy() -> (String, Bomb) { @@ -81,18 +86,20 @@ pub fn proxy() -> (String, Bomb) { let (quittx, quitrx) = channel(); - thread::spawn(move|| { + thread::spawn(move || { let mut file = None; for socket in a.incoming() { - if quitrx.try_recv().is_ok() { break } + if quitrx.try_recv().is_ok() { + break; + } let socket = t!(socket); if file.is_none() { let io = t!(if record { - File::create(&data) - } else { - File::open(&data) - }); + File::create(&data) + } else { + File::open(&data) + }); file = Some(BufStream::new(io)); } @@ -112,7 +119,13 @@ pub fn proxy() -> (String, Bomb) { tx.send(()).unwrap(); }); - (ret, Bomb { accept: a2, rx: rx, iorx: Sink(sink), quit: quittx }) + (ret, + Bomb { + accept: a2, + rx: rx, + iorx: Sink(sink), + quit: quittx, + }) } fn record_http(mut socket: TcpStream, data: &mut BufStream) { @@ -124,7 +137,8 @@ fn record_http(mut socket: TcpStream, data: &mut BufStream) { respond(handle, headers, body, &mut response); t!(socket.write_all(&response)); - t!(write!(data, "===REQUEST {}\n{}\n===RESPONSE {}\n{}\n", + t!(write!(data, + "===REQUEST {}\n{}\n===RESPONSE {}\n{}\n", request.len(), str::from_utf8(&request).unwrap(), response.len(), @@ -145,7 +159,7 @@ fn record_http(mut socket: TcpStream, data: &mut BufStream) { for line in lines { let line = t!(line); if line.len() < 3 { - break + break; } t!(headers.append(&line)); } @@ -166,16 +180,14 @@ fn record_http(mut socket: TcpStream, data: &mut BufStream) { { let mut transfer = handle.transfer(); t!(transfer.header_function(|header| { - headers.push(header.to_owned()); - true - })); + headers.push(header.to_owned()); + true + })); t!(transfer.write_function(|data| { - response.extend(data); - Ok(data.len()) - })); - t!(transfer.read_function(|buf| { - socket.read(buf).map_err(|_| ReadError::Abort) - })); + response.extend(data); + Ok(data.len()) + })); + t!(transfer.read_function(|buf| socket.read(buf).map_err(|_| ReadError::Abort))); t!(transfer.perform()); } @@ -183,15 +195,11 @@ fn record_http(mut socket: TcpStream, data: &mut BufStream) { (handle, headers, response) } - fn respond(mut handle: Easy, - headers: Vec>, - body: Vec, - mut socket: W) { - t!(socket.write_all(format!("HTTP/1.1 {}\r\n", - t!(handle.response_code())).as_bytes())); + fn respond(mut handle: Easy, headers: Vec>, body: Vec, mut socket: W) { + t!(socket.write_all(format!("HTTP/1.1 {}\r\n", t!(handle.response_code())).as_bytes())); for header in headers { if header.starts_with(b"Transfer-Encoding: ") { - continue + continue; } t!(socket.write_all(&header)); t!(socket.write_all(b"\r\n")); @@ -201,8 +209,7 @@ fn record_http(mut socket: TcpStream, data: &mut BufStream) { } } -fn replay_http(socket: TcpStream, data: &mut BufStream, - stdout: &mut Write) { +fn replay_http(socket: TcpStream, data: &mut BufStream, stdout: &mut Write) { let mut writer = socket.try_clone().unwrap(); let socket = BufReader::new(socket); @@ -218,22 +225,35 @@ fn replay_http(socket: TcpStream, data: &mut BufStream, let mut actual_lines = socket.lines().map(|s| s.unwrap()); // validate the headers - let mut expected: HashSet = expected_lines.by_ref() - .take_while(|l| l.len() > 2) - .collect(); + let mut expected: HashSet = expected_lines + .by_ref() + .take_while(|l| l.len() > 2) + .collect(); let mut found = HashSet::new(); t!(writeln!(stdout, "expecting: {:?}", expected)); for line in actual_lines.by_ref().take_while(|l| l.len() > 2) { t!(writeln!(stdout, "received: {}", line.trim())); - if !found.insert(line.clone()) { continue } - if expected.remove(&line) { continue } - if line.starts_with("Date:") { continue } - if line.starts_with("Authorization:") { continue } + if !found.insert(line.clone()) { + continue; + } + if expected.remove(&line) { + continue; + } + if line.starts_with("Date:") { + continue; + } + if line.starts_with("Authorization:") { + continue; + } panic!("unexpected header: {}", line); } for line in expected.iter() { - if line.starts_with("Date:") { continue } - if line.starts_with("Authorization:") { continue } + if line.starts_with("Date:") { + continue; + } + if line.starts_with("Authorization:") { + continue; + } panic!("didn't receive header: {}", line); } @@ -247,10 +267,11 @@ fn replay_http(socket: TcpStream, data: &mut BufStream, let response_size = response.next().unwrap().trim().parse().unwrap(); let mut response = Vec::new(); data.take(response_size).read_to_end(&mut response).unwrap(); - let lines = <[_]>::split(&response[..], |b| *b == b'\n') - .map(|s| str::from_utf8(s).unwrap()); + let lines = <[_]>::split(&response[..], |b| *b == b'\n').map(|s| str::from_utf8(s).unwrap()); for line in lines { - if line.starts_with("Date:") { continue } + if line.starts_with("Date:") { + continue; + } writer.write_all(line.as_bytes()).unwrap(); writer.write_all(b"\r\n").unwrap(); } @@ -262,22 +283,28 @@ impl GhUser { self.init.call_once(|| self.init()); let mut u = ::new_user(self.login); u.gh_access_token = Cow::Owned(self.token()); - return u + return u; } - fn filename(&self) -> PathBuf { cache_file(&format!("gh-{}", self.login)) } + fn filename(&self) -> PathBuf { + cache_file(&format!("gh-{}", self.login)) + } fn token(&self) -> String { let mut token = String::new(); - File::open(&self.filename()).unwrap().read_to_string(&mut token).unwrap(); - return token + File::open(&self.filename()) + .unwrap() + .read_to_string(&mut token) + .unwrap(); + return token; } fn init(&self) { - if fs::metadata(&self.filename()).is_ok() { return } + if fs::metadata(&self.filename()).is_ok() { + return; + } - let password = ::env(&format!("GH_PASS_{}", - self.login.replace("-", "_"))); + let password = ::env(&format!("GH_PASS_{}", self.login.replace("-", "_"))); #[derive(RustcEncodable)] struct Authorization { scopes: Vec, @@ -287,13 +314,15 @@ impl GhUser { } let mut handle = Easy::new(); let url = format!("https://{}:{}@api.github.com/authorizations", - self.login, password); + self.login, + password); let body = json::encode(&Authorization { - scopes: vec!["read:org".to_string()], - note: "crates.io test".to_string(), - client_id: ::env("GH_CLIENT_ID"), - client_secret: ::env("GH_CLIENT_SECRET"), - }).unwrap(); + scopes: vec!["read:org".to_string()], + note: "crates.io test".to_string(), + client_id: ::env("GH_CLIENT_ID"), + client_secret: ::env("GH_CLIENT_SECRET"), + }) + .unwrap(); t!(handle.url(&url)); t!(handle.post(true)); @@ -306,26 +335,26 @@ impl GhUser { let mut response = Vec::new(); { let mut transfer = handle.transfer(); - t!(transfer.read_function(|buf| { - body.read(buf).map_err(|_| ReadError::Abort) - })); + t!(transfer.read_function(|buf| body.read(buf).map_err(|_| ReadError::Abort))); t!(transfer.write_function(|data| { - response.extend(data); - Ok(data.len()) - })); + response.extend(data); + Ok(data.len()) + })); t!(transfer.perform()) } if t!(handle.response_code()) < 200 || t!(handle.response_code()) >= 300 { - panic!("failed to get a 200 {}", - String::from_utf8_lossy(&response)); + panic!("failed to get a 200 {}", String::from_utf8_lossy(&response)); } #[derive(RustcDecodable)] - struct Response { token: String } - let resp: Response = json::decode(str::from_utf8(&response) - .unwrap()).unwrap(); - File::create(&self.filename()).unwrap() - .write_all(&resp.token.as_bytes()).unwrap(); + struct Response { + token: String, + } + let resp: Response = json::decode(str::from_utf8(&response).unwrap()).unwrap(); + File::create(&self.filename()) + .unwrap() + .write_all(&resp.token.as_bytes()) + .unwrap(); } } diff --git a/src/tests/team.rs b/src/tests/team.rs index 52ff6f5d135..d8ddaefd29f 100644 --- a/src/tests/team.rs +++ b/src/tests/team.rs @@ -9,11 +9,21 @@ use record::GhUser; // Teams: `crates-test-org:owners`, `crates-test-org:just-for-crates-2` // tester-1 is on owners only, tester-2 is on both -static GH_USER_1: GhUser = GhUser { login: "crates-tester-1", init: ONCE_INIT }; -static GH_USER_2: GhUser = GhUser { login: "crates-tester-2", init: ONCE_INIT }; - -fn mock_user_on_only_x() -> NewUser<'static> { GH_USER_1.user() } -fn mock_user_on_x_and_y() -> NewUser<'static> { GH_USER_2.user() } +static GH_USER_1: GhUser = GhUser { + login: "crates-tester-1", + init: ONCE_INIT, +}; +static GH_USER_2: GhUser = GhUser { + login: "crates-tester-2", + init: ONCE_INIT, +}; + +fn mock_user_on_only_x() -> NewUser<'static> { + GH_USER_1.user() +} +fn mock_user_on_x_and_y() -> NewUser<'static> { + GH_USER_2.user() +} fn body_for_team_y() -> &'static str { r#"{"users":["github:crates-test-org:just-for-crates-2"]}"# @@ -27,103 +37,111 @@ fn body_for_team_x() -> &'static str { #[test] fn not_github() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_x_and_y(), "foo_not_github"); + let mut req = + ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_not_github"); let body = r#"{"users":["dropbox:foo:foo"]}"#; let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_not_github/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); assert!(json.errors[0].detail.contains("unknown organization"), - "{:?}", json.errors); + "{:?}", + json.errors); } #[test] fn weird_name() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_x_and_y(), "foo_weird_name"); + let mut req = + ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_weird_name"); let body = r#"{"users":["github:foo/../bar:wut"]}"#; let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_weird_name/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); - assert!(json.errors[0].detail.contains("organization cannot contain"), - "{:?}", json.errors); + .with_method(Method::Put) + .with_body(body.as_bytes()))); + assert!(json.errors[0] + .detail + .contains("organization cannot contain"), + "{:?}", + json.errors); } // Test adding team without second `:` #[test] fn one_colon() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_x_and_y(), "foo_one_colon"); + let mut req = ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_one_colon"); let body = r#"{"users":["github:foo"]}"#; let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_one_colon/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); assert!(json.errors[0].detail.contains("missing github team"), - "{:?}", json.errors); + "{:?}", + json.errors); } #[test] fn nonexistent_team() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_x_and_y(), "foo_nonexistent"); + let mut req = + ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_nonexistent"); let body = r#"{"users":["github:crates-test-org:this-does-not-exist"]}"#; let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_nonexistent/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); - assert!(json.errors[0].detail.contains("could not find the github team"), - "{:?}", json.errors); + .with_method(Method::Put) + .with_body(body.as_bytes()))); + assert!(json.errors[0] + .detail + .contains("could not find the github team"), + "{:?}", + json.errors); } // Test adding team as owner when on it #[test] fn add_team_as_member() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_x_and_y(), "foo_team_member"); + let mut req = + ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_team_member"); let body = body_for_team_x(); ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_team_member/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); } // Test adding team as owner when not on in #[test] fn add_team_as_non_member() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_only_x(), "foo_team_non_member"); + let mut req = + ::request_with_user_and_mock_crate(&app, mock_user_on_only_x(), "foo_team_non_member"); let body = body_for_team_y(); let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_team_non_member/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); assert!(json.errors[0].detail.contains("only members"), - "{:?}", json.errors); + "{:?}", + json.errors); } #[test] fn remove_team_as_named_owner() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_x_and_y(), "foo_remove_team"); + let mut req = + ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_remove_team"); let body = body_for_team_x(); ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_remove_team/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); let body = body_for_team_x(); ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_remove_team/owners") - .with_method(Method::Delete) - .with_body(body.as_bytes()))); + .with_method(Method::Delete) + .with_body(body.as_bytes()))); { let conn = app.diesel_database.get().unwrap(); @@ -132,22 +150,23 @@ fn remove_team_as_named_owner() { } let body = ::new_req_body_version_2(::krate("foo_remove_team")); let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_body(&body) - .with_method(Method::Put))); + .with_body(&body) + .with_method(Method::Put))); assert!(json.errors[0].detail.contains("another user"), - "{:?}", json.errors); + "{:?}", + json.errors); } #[test] fn remove_team_as_team_owner() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_x_and_y(), "foo_remove_team_owner"); + let mut req = + ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_remove_team_owner"); let body = body_for_team_x(); ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_remove_team_owner/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); { let conn = app.diesel_database.get().unwrap(); @@ -156,16 +175,17 @@ fn remove_team_as_team_owner() { } let body = body_for_team_x(); let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_remove_team_owner/owners") - .with_method(Method::Delete) - .with_body(body.as_bytes()))); + .with_method(Method::Delete) + .with_body(body.as_bytes()))); assert!(json.errors[0].detail.contains("don't have permission"), - "{:?}", json.errors); + "{:?}", + json.errors); let body = ::new_req_body_version_2(::krate("foo_remove_team_owner")); ok_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_body(&body) - .with_method(Method::Put))); + .with_body(&body) + .with_method(Method::Put))); } // Test trying to publish a krate we don't own @@ -173,13 +193,12 @@ fn remove_team_as_team_owner() { fn publish_not_owned() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_x_and_y(), "foo_not_owned"); + let mut req = ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_not_owned"); let body = body_for_team_y(); ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_not_owned/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); { let conn = app.diesel_database.get().unwrap(); @@ -188,23 +207,24 @@ fn publish_not_owned() { } let body = ::new_req_body_version_2(::krate("foo_not_owned")); let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_body(&body) - .with_method(Method::Put))); + .with_body(&body) + .with_method(Method::Put))); assert!(json.errors[0].detail.contains("another user"), - "{:?}", json.errors); + "{:?}", + json.errors); } // Test trying to publish a krate we do own (but only because of teams) #[test] fn publish_owned() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_x_and_y(), "foo_team_owned"); + let mut req = + ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_team_owned"); let body = body_for_team_x(); ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_team_owned/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); { let conn = app.diesel_database.get().unwrap(); @@ -213,31 +233,31 @@ fn publish_owned() { } let body = ::new_req_body_version_2(::krate("foo_team_owned")); ok_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_body(&body) - .with_method(Method::Put))); + .with_body(&body) + .with_method(Method::Put))); } // Test trying to change owners (when only on an owning team) #[test] fn add_owners_as_team_owner() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_x_and_y(), "foo_add_owner"); + let mut req = ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_add_owner"); let body = body_for_team_x(); ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_add_owner/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); { let conn = app.diesel_database.get().unwrap(); let user = mock_user_on_only_x().create_or_update(&conn).unwrap(); ::sign_in_as(&mut req, &user); } - let body = r#"{"users":["FlashCat"]}"#; // User doesn't matter + let body = r#"{"users":["FlashCat"]}"#; // User doesn't matter let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_add_owner/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); assert!(json.errors[0].detail.contains("don't have permission"), - "{:?}", json.errors); + "{:?}", + json.errors); } diff --git a/src/tests/user.rs b/src/tests/user.rs index 2372eec8c34..04453488299 100644 --- a/src/tests/user.rs +++ b/src/tests/user.rs @@ -7,11 +7,19 @@ use cargo_registry::user::{User, NewUser, EncodableUser}; use cargo_registry::version::EncodableVersion; #[derive(RustcDecodable)] -struct AuthResponse { url: String, state: String } +struct AuthResponse { + url: String, + state: String, +} #[derive(RustcDecodable)] -struct MeResponse { user: EncodableUser, api_token: String } +struct MeResponse { + user: EncodableUser, + api_token: String, +} #[derive(RustcDecodable)] -struct UserShowResponse { user: EncodableUser } +struct UserShowResponse { + user: EncodableUser, +} #[test] fn auth_gives_a_token() { @@ -41,16 +49,14 @@ fn user_insert() { assert_eq!(t!(User::find_by_api_token(&tx, &user.api_token)), user); assert_eq!(t!(User::find(&tx, user.id)), user); - assert_eq!(t!(User::find_or_insert(&tx, 1, "foo", None, None, None, - "bar")), user); - let user2 = t!(User::find_or_insert(&tx, 1, "foo", None, None, None, - "baz")); + assert_eq!(t!(User::find_or_insert(&tx, 1, "foo", None, None, None, "bar")), + user); + let user2 = t!(User::find_or_insert(&tx, 1, "foo", None, None, None, "baz")); assert!(user != user2); assert_eq!(user.id, user2.id); assert_eq!(user2.gh_access_token, "baz"); - let user3 = t!(User::find_or_insert(&tx, 1, "bar", None, None, None, - "baz")); + let user3 = t!(User::find_or_insert(&tx, 1, "bar", None, None, None, "baz")); assert!(user != user3); assert_eq!(user.id, user3.id); assert_eq!(user3.gh_login, "bar"); @@ -97,8 +103,7 @@ fn show() { fn reset_token() { let (_b, app, middle) = ::app(); let mut req = ::req(app, Method::Put, "/me/reset_token"); - let user = User::find_or_insert(req.tx().unwrap(), 1, "foo", None, - None, None, "bar").unwrap(); + let user = User::find_or_insert(req.tx().unwrap(), 1, "foo", None, None, None, "bar").unwrap(); ::sign_in_as(&mut req, &user); ok_resp!(middle.call(&mut req)); @@ -112,11 +117,8 @@ fn crates_by_user_id() { let u; { let conn = app.diesel_database.get().unwrap(); - u = ::new_user("foo") - .create_or_update(&conn) - .unwrap(); - ::CrateBuilder::new("foo_my_packages", u.id) - .expect_build(&conn); + u = ::new_user("foo").create_or_update(&conn).unwrap(); + ::CrateBuilder::new("foo_my_packages", u.id).expect_build(&conn); } let mut req = ::req(app, Method::Get, "/api/v1/crates"); @@ -124,7 +126,9 @@ fn crates_by_user_id() { let mut response = ok_resp!(middle.call(&mut req)); #[derive(RustcDecodable)] - struct Response { crates: Vec } + struct Response { + crates: Vec, + } let response: Response = ::json(&mut response); assert_eq!(response.crates.len(), 1); } @@ -136,7 +140,10 @@ fn following() { versions: Vec, meta: Meta, } - #[derive(RustcDecodable)] struct Meta { more: bool } + #[derive(RustcDecodable)] + struct Meta { + more: bool, + } let (_b, app, middle) = ::app(); let mut req = ::req(app.clone(), Method::Get, "/"); @@ -154,35 +161,33 @@ fn following() { .expect_build(&conn); } - let mut response = ok_resp!(middle.call(req.with_path("/me/updates") - .with_method(Method::Get))); + let mut response = ok_resp!(middle.call(req.with_path("/me/updates").with_method(Method::Get))); let r = ::json::(&mut response); assert_eq!(r.versions.len(), 0); assert_eq!(r.meta.more, false); ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_fighters/follow") - .with_method(Method::Put))); + .with_method(Method::Put))); ok_resp!(middle.call(req.with_path("/api/v1/crates/bar_fighters/follow") - .with_method(Method::Put))); + .with_method(Method::Put))); - let mut response = ok_resp!(middle.call(req.with_path("/me/updates") - .with_method(Method::Get))); + let mut response = ok_resp!(middle.call(req.with_path("/me/updates").with_method(Method::Get))); let r = ::json::(&mut response); assert_eq!(r.versions.len(), 2); assert_eq!(r.meta.more, false); let mut response = ok_resp!(middle.call(req.with_path("/me/updates") - .with_method(Method::Get) - .with_query("per_page=1"))); + .with_method(Method::Get) + .with_query("per_page=1"))); let r = ::json::(&mut response); assert_eq!(r.versions.len(), 1); assert_eq!(r.meta.more, true); ok_resp!(middle.call(req.with_path("/api/v1/crates/bar_fighters/follow") - .with_method(Method::Delete))); + .with_method(Method::Delete))); let mut response = ok_resp!(middle.call(req.with_path("/me/updates") - .with_method(Method::Get) - .with_query("page=2&per_page=1"))); + .with_method(Method::Get) + .with_query("page=2&per_page=1"))); let r = ::json::(&mut response); assert_eq!(r.versions.len(), 0); assert_eq!(r.meta.more, false); diff --git a/src/tests/version.rs b/src/tests/version.rs index 00501ed7449..db8851d1447 100644 --- a/src/tests/version.rs +++ b/src/tests/version.rs @@ -8,9 +8,13 @@ use cargo_registry::db::RequestTransaction; use cargo_registry::version::{EncodableVersion, Version}; #[derive(RustcDecodable)] -struct VersionList { versions: Vec } +struct VersionList { + versions: Vec, +} #[derive(RustcDecodable)] -struct VersionResponse { version: EncodableVersion } +struct VersionResponse { + version: EncodableVersion, +} fn sv(s: &str) -> semver::Version { semver::Version::parse(s).unwrap() @@ -46,8 +50,7 @@ fn show() { let v = { let conn = app.diesel_database.get().unwrap(); let user = ::new_user("foo").create_or_update(&conn).unwrap(); - let krate = ::CrateBuilder::new("foo_vers_show", user.id) - .expect_build(&conn); + let krate = ::CrateBuilder::new("foo_vers_show", user.id).expect_build(&conn); ::new_version(krate.id, "2.0.0").save(&conn, &[]).unwrap() }; req.with_path(&format!("/api/v1/versions/{}", v.id)); diff --git a/src/upload.rs b/src/upload.rs index 7c64b456bf2..e9f8ff2e15b 100644 --- a/src/upload.rs +++ b/src/upload.rs @@ -55,14 +55,14 @@ impl Decodable for CrateName { return Err(d.error(&format!("invalid crate name specified: {}. \ Valid crate names must start with a letter; contain only \ letters, numbers, hyphens, or underscores; and have {} or \ - fewer characters.", s, MAX_NAME_LENGTH))) + fewer characters.", s, MAX_NAME_LENGTH))); } Ok(CrateName(s)) } } -impl PartialEq for CrateName where - String: PartialEq, +impl PartialEq for CrateName + where String: PartialEq { fn eq(&self, rhs: &T) -> bool { self.0 == *rhs @@ -73,7 +73,7 @@ impl Decodable for Keyword { fn decode(d: &mut D) -> Result { let s = d.read_str()?; if !CrateKeyword::valid_name(&s) { - return Err(d.error(&format!("invalid keyword specified: {}", s))) + return Err(d.error(&format!("invalid keyword specified: {}", s))); } Ok(Keyword(s)) } @@ -89,7 +89,7 @@ impl Decodable for Feature { fn decode(d: &mut D) -> Result { let s = d.read_str()?; if !Crate::valid_feature_name(&s) { - return Err(d.error(&format!("invalid feature name specified: {}", s))) + return Err(d.error(&format!("invalid feature name specified: {}", s))); } Ok(Feature(s)) } @@ -115,8 +115,8 @@ impl Decodable for CrateVersionReq { } } -impl PartialEq for CrateVersionReq where - semver::VersionReq: PartialEq, +impl PartialEq for CrateVersionReq + where semver::VersionReq: PartialEq { fn eq(&self, rhs: &T) -> bool { self.0 == *rhs @@ -127,12 +127,12 @@ impl Decodable for KeywordList { fn decode(d: &mut D) -> Result { let inner: Vec = Decodable::decode(d)?; if inner.len() > 5 { - return Err(d.error("a maximum of 5 keywords per crate are allowed")) + return Err(d.error("a maximum of 5 keywords per crate are allowed")); } for val in &inner { if val.len() > 20 { return Err(d.error("keywords must contain less than 20 \ - characters")) + characters")); } } Ok(KeywordList(inner)) @@ -143,7 +143,7 @@ impl Decodable for CategoryList { fn decode(d: &mut D) -> Result { let inner: Vec = Decodable::decode(d)?; if inner.len() > 5 { - return Err(d.error("a maximum of 5 categories per crate are allowed")) + return Err(d.error("a maximum of 5 categories per crate are allowed")); } Ok(CategoryList(inner)) } @@ -156,8 +156,10 @@ impl Decodable for DependencyKind { "dev" => Ok(DependencyKind::Dev), "build" => Ok(DependencyKind::Build), "normal" => Ok(DependencyKind::Normal), - s => Err(d.error(&format!("invalid dependency kind `{}`, must be \ - one of dev, build, or normal", s))), + s => { + Err(d.error(&format!("invalid dependency kind `{}`, must be \ + one of dev, build, or normal", s))) + } } } } @@ -224,40 +226,56 @@ impl Encodable for DependencyKind { impl Deref for CrateName { type Target = str; - fn deref(&self) -> &str { &self.0 } + fn deref(&self) -> &str { + &self.0 + } } impl Deref for Keyword { type Target = str; - fn deref(&self) -> &str { &self.0 } + fn deref(&self) -> &str { + &self.0 + } } impl Deref for Category { type Target = str; - fn deref(&self) -> &str { &self.0 } + fn deref(&self) -> &str { + &self.0 + } } impl Deref for Feature { type Target = str; - fn deref(&self) -> &str { &self.0 } + fn deref(&self) -> &str { + &self.0 + } } impl Deref for CrateVersion { type Target = semver::Version; - fn deref(&self) -> &semver::Version { &self.0 } + fn deref(&self) -> &semver::Version { + &self.0 + } } impl Deref for CrateVersionReq { type Target = semver::VersionReq; - fn deref(&self) -> &semver::VersionReq { &self.0 } + fn deref(&self) -> &semver::VersionReq { + &self.0 + } } impl Deref for KeywordList { type Target = [Keyword]; - fn deref(&self) -> &[Keyword] { &self.0 } + fn deref(&self) -> &[Keyword] { + &self.0 + } } impl Deref for CategoryList { type Target = [Category]; - fn deref(&self) -> &[Category] { &self.0 } + fn deref(&self) -> &[Category] { + &self.0 + } } diff --git a/src/uploaders.rs b/src/uploaders.rs index f31e045bb20..f022199090f 100644 --- a/src/uploaders.rs +++ b/src/uploaders.rs @@ -14,7 +14,10 @@ use std::io; pub enum Uploader { /// For production usage, uploads and redirects to s3. /// For test usage with a proxy. - S3 { bucket: s3::Bucket, proxy: Option }, + S3 { + bucket: s3::Bucket, + proxy: Option, + }, /// For development usage only: "uploads" crate files to `dist` and serves them /// from there as well to enable local publishing and download @@ -32,14 +35,13 @@ impl Uploader { } } - pub fn crate_location(&self, crate_name: &str, version: &str) - -> Option { + pub fn crate_location(&self, crate_name: &str, version: &str) -> Option { match *self { Uploader::S3 { ref bucket, .. } => { Some(format!("https://{}/{}", bucket.host(), Uploader::crate_path(crate_name, version))) - }, + } Uploader::Local => { Some(format!("/local_uploads/{}", Uploader::crate_path(crate_name, version))) @@ -53,7 +55,12 @@ impl Uploader { format!("crates/{}/{}-{}.crate", name, name, version) } - pub fn upload(&self, req: &mut Request, krate: &Crate, max: u64, vers: &semver::Version) -> CargoResult<(Vec, Bomb)> { + pub fn upload(&self, + req: &mut Request, + krate: &Crate, + max: u64, + vers: &semver::Version) + -> CargoResult<(Vec, Bomb)> { match *self { Uploader::S3 { ref bucket, .. } => { let mut handle = req.app().handle(); @@ -64,36 +71,44 @@ impl Uploader { let mut body = HashingReader::new(body); let mut response = Vec::new(); { - let mut s3req = bucket.put(&mut handle, &path, &mut body, - "application/x-tar", - length as u64); - s3req.write_function(|data| { - response.extend(data); - Ok(data.len()) - }).unwrap(); - s3req.perform().chain_error(|| { - internal(&format_args!("failed to upload to S3: `{}`", path)) - })?; + let mut s3req = bucket.put(&mut handle, + &path, + &mut body, + "application/x-tar", + length as u64); + s3req + .write_function(|data| { + response.extend(data); + Ok(data.len()) + }) + .unwrap(); + s3req + .perform() + .chain_error(|| { + internal(&format_args!("failed to upload to S3: `{}`", path)) + })?; } (response, body.finalize()) }; if handle.response_code().unwrap() != 200 { let response = String::from_utf8_lossy(&response); return Err(internal(&format_args!("failed to get a 200 response from S3: {}", - response))) + response))); } - Ok((cksum, Bomb { - app: req.app().clone(), - path: Some(path), - })) - }, + Ok((cksum, + Bomb { + app: req.app().clone(), + path: Some(path), + })) + } Uploader::Local => { let path = Uploader::crate_path(&krate.name, &vers.to_string()); - let crate_filename = env::current_dir().unwrap() - .join("dist") - .join("local_uploads") - .join(path); + let crate_filename = env::current_dir() + .unwrap() + .join("dist") + .join("local_uploads") + .join(path); let crate_dir = crate_filename.parent().unwrap(); fs::create_dir_all(crate_dir)?; @@ -109,12 +124,19 @@ impl Uploader { body.finalize() }; - Ok((cksum, Bomb { - app: req.app().clone(), - path: crate_filename.to_str().map(String::from) - })) - }, - Uploader::NoOp => Ok((vec![], Bomb { app: req.app().clone(), path: None })), + Ok((cksum, + Bomb { + app: req.app().clone(), + path: crate_filename.to_str().map(String::from), + })) + } + Uploader::NoOp => { + Ok((vec![], + Bomb { + app: req.app().clone(), + path: None, + })) + } } } @@ -124,7 +146,7 @@ impl Uploader { let mut handle = app.handle(); bucket.delete(&mut handle, path).perform()?; Ok(()) - }, + } Uploader::Local => { fs::remove_file(path)?; Ok(()) diff --git a/src/user/middleware.rs b/src/user/middleware.rs index 43959aea975..2b5b256b606 100644 --- a/src/user/middleware.rs +++ b/src/user/middleware.rs @@ -12,9 +12,11 @@ use util::errors::{CargoResult, Unauthorized, ChainError, std_error}; pub struct Middleware; impl conduit_middleware::Middleware for Middleware { - fn before(&self, req: &mut Request) -> Result<(), Box> { + fn before(&self, req: &mut Request) -> Result<(), Box> { // Check if the request has a session cookie with a `user_id` property inside - let id = { req.session().get("user_id").and_then(|s| s.parse().ok()) }; + let id = { + req.session().get("user_id").and_then(|s| s.parse().ok()) + }; let user = match id { @@ -39,10 +41,10 @@ impl conduit_middleware::Middleware for Middleware { let tx = req.tx().map_err(std_error)?; match User::find_by_api_token(tx, headers[0]) { Ok(user) => user, - Err(..) => return Ok(()) + Err(..) => return Ok(()), } } - None => return Ok(()) + None => return Ok(()), } } }; @@ -59,6 +61,8 @@ pub trait RequestUser { impl<'a> RequestUser for Request + 'a { fn user(&self) -> CargoResult<&User> { - self.extensions().find::().chain_error(|| Unauthorized) + self.extensions() + .find::() + .chain_error(|| Unauthorized) } } diff --git a/src/user/mod.rs b/src/user/mod.rs index d6359cc7c37..c377920ea64 100644 --- a/src/user/mod.rs +++ b/src/user/mod.rs @@ -1,5 +1,5 @@ use conduit::{Request, Response}; -use conduit_cookie::{RequestSession}; +use conduit_cookie::RequestSession; use conduit_router::RequestParams; use diesel::prelude::*; use diesel::pg::PgConnection; @@ -51,7 +51,8 @@ impl<'a> NewUser<'a> { email: Option<&'a str>, name: Option<&'a str>, gh_avatar: Option<&'a str>, - gh_access_token: &'a str) -> Self { + gh_access_token: &'a str) + -> Self { NewUser { gh_id: gh_id, gh_login: gh_login, @@ -90,26 +91,23 @@ pub struct EncodableUser { impl User { /// Queries the database for a user with a certain `gh_login` value. - pub fn find_by_login(conn: &GenericConnection, - login: &str) -> CargoResult { + pub fn find_by_login(conn: &GenericConnection, login: &str) -> CargoResult { let stmt = conn.prepare("SELECT * FROM users WHERE gh_login = $1")?; let rows = stmt.query(&[&login])?; - let row = rows.iter().next().chain_error(|| { - NotFound - })?; + let row = rows.iter().next().chain_error(|| NotFound)?; Ok(Model::from_row(&row)) } /// Queries the database for a user with a certain `api_token` value. - pub fn find_by_api_token(conn: &GenericConnection, - token: &str) -> CargoResult { + pub fn find_by_api_token(conn: &GenericConnection, token: &str) -> CargoResult { let stmt = conn.prepare("SELECT * FROM users \ WHERE api_token = $1 LIMIT 1")?; let rows = stmt.query(&[&token])?; - rows.iter().next().map(|r| Model::from_row(&r)).chain_error(|| { - NotFound - }) + rows.iter() + .next() + .map(|r| Model::from_row(&r)) + .chain_error(|| NotFound) } /// Updates a user or inserts a new user into the database. @@ -119,7 +117,8 @@ impl User { email: Option<&str>, name: Option<&str>, avatar: Option<&str>, - access_token: &str) -> CargoResult { + access_token: &str) + -> CargoResult { // TODO: this is racy, but it looks like any other solution is... // interesting! For now just do the racy thing which will report // more errors than it needs to. @@ -132,12 +131,7 @@ impl User { gh_login = $5 WHERE gh_id = $6 RETURNING *")?; - let rows = stmt.query(&[&access_token, - &email, - &name, - &avatar, - &login, - &id])?; + let rows = stmt.query(&[&access_token, &email, &name, &avatar, &login, &id])?; if let Some(ref row) = rows.iter().next() { return Ok(Model::from_row(row)); } @@ -146,20 +140,22 @@ impl User { gh_login, name, gh_avatar, gh_id) VALUES ($1, $2, $3, $4, $5, $6) RETURNING *")?; - let rows = stmt.query(&[&email, - &access_token, - &login, - &name, - &avatar, - &id])?; - Ok(Model::from_row(&rows.iter().next().chain_error(|| { - internal("no user with email we just found") - })?)) + let rows = stmt.query(&[&email, &access_token, &login, &name, &avatar, &id])?; + Ok(Model::from_row(&rows.iter() + .next() + .chain_error(|| internal("no user with email we just found"))?)) } /// Converts this `User` model into an `EncodableUser` for JSON serialization. pub fn encodable(self) -> EncodableUser { - let User { id, email, name, gh_login, gh_avatar, .. } = self; + let User { + id, + email, + name, + gh_login, + gh_avatar, + .. + } = self; let url = format!("https://github.com/{}", gh_login); EncodableUser { id: id, @@ -186,7 +182,9 @@ impl Model for User { } } - fn table_name(_: Option) -> &'static str { "users" } + fn table_name(_: Option) -> &'static str { + "users" + } } /// Handles the `GET /authorize_url` route. @@ -207,13 +205,20 @@ impl Model for User { pub fn github_authorize(req: &mut Request) -> CargoResult { // Generate a random 16 char ASCII string let state: String = thread_rng().gen_ascii_chars().take(16).collect(); - req.session().insert("github_oauth_state".to_string(), state.clone()); + req.session() + .insert("github_oauth_state".to_string(), state.clone()); let url = req.app().github.authorize_url(state.clone()); #[derive(RustcEncodable)] - struct R { url: String, state: String } - Ok(req.json(&R { url: url.to_string(), state: state })) + struct R { + url: String, + state: String, + } + Ok(req.json(&R { + url: url.to_string(), + state: state, + })) } /// Handles the `GET /authorize` route. @@ -256,7 +261,7 @@ pub fn github_access_token(req: &mut Request) -> CargoResult { let session_state = req.session().remove(&"github_oauth_state".to_string()); let session_state = session_state.as_ref().map(|a| &a[..]); if Some(&state[..]) != session_state { - return Err(human("invalid state parameter")) + return Err(human("invalid state parameter")); } } @@ -270,7 +275,9 @@ pub fn github_access_token(req: &mut Request) -> CargoResult { } // Fetch the access token from github using the code we just got - let token = req.app().github.exchange(code.clone()) + let token = req.app() + .github + .exchange(code.clone()) .map_err(|s| human(&s))?; let (handle, resp) = http::github(req.app(), "/user", &token)?; @@ -279,14 +286,12 @@ pub fn github_access_token(req: &mut Request) -> CargoResult { let user = User::find_or_insert(req.tx()?, ghuser.id, &ghuser.login, - ghuser.email.as_ref() - .map(|s| &s[..]), - ghuser.name.as_ref() - .map(|s| &s[..]), - ghuser.avatar_url.as_ref() - .map(|s| &s[..]), + ghuser.email.as_ref().map(|s| &s[..]), + ghuser.name.as_ref().map(|s| &s[..]), + ghuser.avatar_url.as_ref().map(|s| &s[..]), &token.access_token)?; - req.session().insert("user_id".to_string(), user.id.to_string()); + req.session() + .insert("user_id".to_string(), user.id.to_string()); req.mut_extensions().insert(user); me(req) } @@ -303,13 +308,17 @@ pub fn reset_token(req: &mut Request) -> CargoResult { let conn = req.tx()?; let rows = conn.query("UPDATE users SET api_token = DEFAULT \ - WHERE id = $1 RETURNING api_token", &[&user.id])?; - let token = rows.iter().next() + WHERE id = $1 RETURNING api_token", + &[&user.id])?; + let token = rows.iter() + .next() .map(|r| r.get("api_token")) .chain_error(|| NotFound)?; #[derive(RustcEncodable)] - struct R { api_token: String } + struct R { + api_token: String, + } Ok(req.json(&R { api_token: token })) } @@ -318,9 +327,15 @@ pub fn me(req: &mut Request) -> CargoResult { let user = req.user()?; #[derive(RustcEncodable)] - struct R { user: EncodableUser, api_token: String } + struct R { + user: EncodableUser, + api_token: String, + } let token = user.api_token.clone(); - Ok(req.json(&R{ user: user.clone().encodable(), api_token: token })) + Ok(req.json(&R { + user: user.clone().encodable(), + api_token: token, + })) } /// Handles the `GET /users/:user_id` route. @@ -329,14 +344,13 @@ pub fn show(req: &mut Request) -> CargoResult { let name = &req.params()["user_id"]; let conn = req.db_conn()?; - let user = users.filter(gh_login.eq(name)) - .first::(&*conn)?; + let user = users.filter(gh_login.eq(name)).first::(&*conn)?; #[derive(RustcEncodable)] struct R { user: EncodableUser, } - Ok(req.json(&R{ user: user.encodable() })) + Ok(req.json(&R { user: user.encodable() })) } @@ -349,27 +363,23 @@ pub fn updates(req: &mut Request) -> CargoResult { let (offset, limit) = req.pagination(10, 100)?; let conn = req.db_conn()?; - let followed_crates = Follow::belonging_to(user) - .select(follows::crate_id); - let data = versions::table.inner_join(crates::table) + let followed_crates = Follow::belonging_to(user).select(follows::crate_id); + let data = versions::table + .inner_join(crates::table) .filter(crates::id.eq(any(followed_crates))) .order(versions::created_at.desc()) .limit(limit) .offset(offset) - .select(( - versions::all_columns, - crates::name, - sql::("COUNT(*) OVER ()"), - )) + .select((versions::all_columns, crates::name, sql::("COUNT(*) OVER ()"))) .load::<(Version, String, i64)>(&*conn)?; let more = data.get(0) .map(|&(_, _, count)| count > offset + limit) .unwrap_or(false); - let versions = data.into_iter().map(|(version, crate_name, _)| { - version.encodable(&crate_name) - }).collect(); + let versions = data.into_iter() + .map(|(version, crate_name, _)| version.encodable(&crate_name)) + .collect(); #[derive(RustcEncodable)] struct R { @@ -377,8 +387,13 @@ pub fn updates(req: &mut Request) -> CargoResult { meta: Meta, } #[derive(RustcEncodable)] - struct Meta { more: bool } - Ok(req.json(&R{ versions: versions, meta: Meta { more: more } })) + struct Meta { + more: bool, + } + Ok(req.json(&R { + versions: versions, + meta: Meta { more: more }, + })) } #[cfg(test)] @@ -401,9 +416,11 @@ mod tests { fn new_users_have_different_api_tokens() { let conn = connection(); let user1 = NewUser::new(1, "foo", None, None, None, "foo") - .create_or_update(&conn).unwrap(); + .create_or_update(&conn) + .unwrap(); let user2 = NewUser::new(2, "bar", None, None, None, "bar") - .create_or_update(&conn).unwrap(); + .create_or_update(&conn) + .unwrap(); assert_ne!(user1.id, user2.id); assert_ne!(user1.api_token, user2.api_token); @@ -414,10 +431,12 @@ mod tests { fn updating_existing_user_doesnt_change_api_token() { let conn = connection(); let user_after_insert = NewUser::new(1, "foo", None, None, None, "foo") - .create_or_update(&conn).unwrap(); + .create_or_update(&conn) + .unwrap(); let original_token = user_after_insert.api_token; NewUser::new(1, "bar", None, None, None, "bar_token") - .create_or_update(&conn).unwrap(); + .create_or_update(&conn) + .unwrap(); let mut users = users::table.load::(&conn).unwrap(); assert_eq!(1, users.len()); let user = users.pop().unwrap(); diff --git a/src/util/errors.rs b/src/util/errors.rs index 6fa45c96d83..ffaae1a0e5c 100644 --- a/src/util/errors.rs +++ b/src/util/errors.rs @@ -3,30 +3,41 @@ use std::error::Error; use std::fmt; use conduit::Response; -use diesel::result::{Error as DieselError}; +use diesel::result::Error as DieselError; use util::json_response; -#[derive(RustcEncodable)] struct StringError { detail: String } -#[derive(RustcEncodable)] struct Bad { errors: Vec } +#[derive(RustcEncodable)] +struct StringError { + detail: String, +} +#[derive(RustcEncodable)] +struct Bad { + errors: Vec, +} // ============================================================================= // CargoError trait pub trait CargoError: Send + fmt::Display + 'static { fn description(&self) -> &str; - fn cause(&self) -> Option<&(CargoError)> { None } + fn cause(&self) -> Option<&(CargoError)> { + None + } fn response(&self) -> Option { if self.human() { Some(json_response(&Bad { - errors: vec![StringError { detail: self.description().to_string() }] - })) + errors: + vec![StringError { detail: self.description().to_string() }], + })) } else { self.cause().and_then(|cause| cause.response()) } } - fn human(&self) -> bool { false } + fn human(&self) -> bool { + false + } } impl fmt::Debug for Box { @@ -36,16 +47,32 @@ impl fmt::Debug for Box { } impl CargoError for Box { - fn description(&self) -> &str { (**self).description() } - fn cause(&self) -> Option<&CargoError> { (**self).cause() } - fn human(&self) -> bool { (**self).human() } - fn response(&self) -> Option { (**self).response() } + fn description(&self) -> &str { + (**self).description() + } + fn cause(&self) -> Option<&CargoError> { + (**self).cause() + } + fn human(&self) -> bool { + (**self).human() + } + fn response(&self) -> Option { + (**self).response() + } } impl CargoError for Box { - fn description(&self) -> &str { (**self).description() } - fn cause(&self) -> Option<&CargoError> { (**self).cause() } - fn human(&self) -> bool { (**self).human() } - fn response(&self) -> Option { (**self).response() } + fn description(&self) -> &str { + (**self).description() + } + fn cause(&self) -> Option<&CargoError> { + (**self).cause() + } + fn human(&self) -> bool { + (**self).human() + } + fn response(&self) -> Option { + (**self).response() + } } pub type CargoResult = Result>; @@ -55,7 +82,8 @@ pub type CargoResult = Result>; pub trait ChainError { fn chain_error(self, callback: F) -> CargoResult - where E: CargoError, F: FnOnce() -> E; + where E: CargoError, + F: FnOnce() -> E; } struct ChainedError { @@ -63,9 +91,13 @@ struct ChainedError { cause: Box, } -impl ChainError for F where F: FnOnce() -> CargoResult { +impl ChainError for F + where F: FnOnce() -> CargoResult +{ fn chain_error(self, callback: C) -> CargoResult - where E: CargoError, C: FnOnce() -> E { + where E: CargoError, + C: FnOnce() -> E + { self().chain_error(callback) } } @@ -73,19 +105,23 @@ impl ChainError for F where F: FnOnce() -> CargoResult { impl ChainError for Result { #[allow(trivial_casts)] fn chain_error(self, callback: C) -> CargoResult - where E2: CargoError, C: FnOnce() -> E2 { + where E2: CargoError, + C: FnOnce() -> E2 + { self.map_err(move |err| { - Box::new(ChainedError { - error: callback(), - cause: Box::new(err), - }) as Box - }) + Box::new(ChainedError { + error: callback(), + cause: Box::new(err), + }) as Box + }) } } impl ChainError for Option { fn chain_error(self, callback: C) -> CargoResult - where E: CargoError, C: FnOnce() -> E { + where E: CargoError, + C: FnOnce() -> E + { match self { Some(t) => Ok(t), None => Err(Box::new(callback())), @@ -94,10 +130,18 @@ impl ChainError for Option { } impl CargoError for ChainedError { - fn description(&self) -> &str { self.error.description() } - fn cause(&self) -> Option<&CargoError> { Some(&*self.cause) } - fn response(&self) -> Option { self.error.response() } - fn human(&self) -> bool { self.error.human() } + fn description(&self) -> &str { + self.error.description() + } + fn cause(&self) -> Option<&CargoError> { + Some(&*self.cause) + } + fn response(&self) -> Option { + self.error.response() + } + fn human(&self) -> bool { + self.error.human() + } } impl fmt::Display for ChainedError { @@ -119,7 +163,9 @@ impl From for Box { struct Shim(E); impl CargoError for Shim { - fn description(&self) -> &str { Error::description(&self.0) } + fn description(&self) -> &str { + Error::description(&self.0) + } } impl fmt::Display for Shim { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -131,10 +177,14 @@ impl From for Box { } impl CargoError for ::curl::Error { - fn description(&self) -> &str { Error::description(self) } + fn description(&self) -> &str { + Error::description(self) + } } impl CargoError for ::rustc_serialize::json::DecoderError { - fn description(&self) -> &str { Error::description(self) } + fn description(&self) -> &str { + Error::description(self) + } } // ============================================================================= @@ -158,20 +208,27 @@ impl fmt::Display for ConcreteCargoError { } impl CargoError for ConcreteCargoError { - fn description(&self) -> &str { &self.description } - fn cause(&self) -> Option<&CargoError> { self.cause.as_ref().map(|c| &**c) } - fn human(&self) -> bool { self.human } + fn description(&self) -> &str { + &self.description + } + fn cause(&self) -> Option<&CargoError> { + self.cause.as_ref().map(|c| &**c) + } + fn human(&self) -> bool { + self.human + } } pub struct NotFound; impl CargoError for NotFound { - fn description(&self) -> &str { "not found" } + fn description(&self) -> &str { + "not found" + } fn response(&self) -> Option { - let mut response = json_response(&Bad { - errors: vec![StringError { detail: "Not Found".to_string() }], - }); + let mut response = + json_response(&Bad { errors: vec![StringError { detail: "Not Found".to_string() }] }); response.status = (404, "Not Found"); Some(response) } @@ -186,14 +243,16 @@ impl fmt::Display for NotFound { pub struct Unauthorized; impl CargoError for Unauthorized { - fn description(&self) -> &str { "unauthorized" } + fn description(&self) -> &str { + "unauthorized" + } fn response(&self) -> Option { let mut response = json_response(&Bad { - errors: vec![StringError { + errors: vec![StringError { detail: "must be logged in to perform that action".to_string(), }], - }); + }); response.status = (403, "Forbidden"); Some(response) } @@ -207,36 +266,38 @@ impl fmt::Display for Unauthorized { pub fn internal_error(error: &str, detail: &str) -> Box { Box::new(ConcreteCargoError { - description: error.to_string(), - detail: Some(detail.to_string()), - cause: None, - human: false, - }) + description: error.to_string(), + detail: Some(detail.to_string()), + cause: None, + human: false, + }) } pub fn internal(error: &S) -> Box { Box::new(ConcreteCargoError { - description: error.to_string(), - detail: None, - cause: None, - human: false, - }) + description: error.to_string(), + detail: None, + cause: None, + human: false, + }) } pub fn human(error: &S) -> Box { Box::new(ConcreteCargoError { - description: error.to_string(), - detail: None, - cause: None, - human: true, - }) + description: error.to_string(), + detail: None, + cause: None, + human: true, + }) } -pub fn std_error(e: Box) -> Box { +pub fn std_error(e: Box) -> Box { #[derive(Debug)] struct E(Box); impl Error for E { - fn description(&self) -> &str { self.0.description() } + fn description(&self) -> &str { + self.0.description() + } } impl fmt::Display for E { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/util/head.rs b/src/util/head.rs index 5f931ab0ee1..3202c4e4ec1 100644 --- a/src/util/head.rs +++ b/src/util/head.rs @@ -18,19 +18,23 @@ impl AroundMiddleware for Head { } impl Handler for Head { - fn call(&self, req: &mut Request) -> Result> { + fn call(&self, req: &mut Request) -> Result> { if req.method() == Method::Head { let mut req = RequestProxy { other: req, path: None, method: Some(Method::Get), }; - self.handler.as_ref().unwrap().call(&mut req).map(|r| { - Response { - body: Box::new(io::empty()), - ..r - } - }) + self.handler + .as_ref() + .unwrap() + .call(&mut req) + .map(|r| { + Response { + body: Box::new(io::empty()), + ..r + } + }) } else { self.handler.as_ref().unwrap().call(req) } diff --git a/src/util/io_util.rs b/src/util/io_util.rs index 9ebc2308043..749fbab5634 100644 --- a/src/util/io_util.rs +++ b/src/util/io_util.rs @@ -16,8 +16,7 @@ impl Read for LimitErrorReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { match self.inner.read(buf) { Ok(0) if self.inner.limit() == 0 => { - Err(io::Error::new(io::ErrorKind::Other, - "maximum limit reached when reading")) + Err(io::Error::new(io::ErrorKind::Other, "maximum limit reached when reading")) } e => e, } @@ -27,19 +26,14 @@ impl Read for LimitErrorReader { pub fn read_le_u32(r: &mut R) -> io::Result { let mut b = [0; 4]; read_fill(r, &mut b)?; - Ok( (b[0] as u32) | - ((b[1] as u32) << 8) | - ((b[2] as u32) << 16) | - ((b[3] as u32) << 24)) + Ok((b[0] as u32) | ((b[1] as u32) << 8) | ((b[2] as u32) << 16) | ((b[3] as u32) << 24)) } -pub fn read_fill(r: &mut R, mut slice: &mut [u8]) - -> io::Result<()> { +pub fn read_fill(r: &mut R, mut slice: &mut [u8]) -> io::Result<()> { while !slice.is_empty() { let n = r.read(slice)?; if n == 0 { - return Err(io::Error::new(io::ErrorKind::Other, - "end of file reached")) + return Err(io::Error::new(io::ErrorKind::Other, "end of file reached")); } slice = &mut mem::replace(&mut slice, &mut [])[n..]; } diff --git a/src/util/lazy_cell.rs b/src/util/lazy_cell.rs index 9ab36f7430f..e530473d597 100644 --- a/src/util/lazy_cell.rs +++ b/src/util/lazy_cell.rs @@ -33,7 +33,9 @@ impl LazyCell { } /// Test whether this cell has been previously filled. - pub fn filled(&self) -> bool { self.inner.borrow().is_some() } + pub fn filled(&self) -> bool { + self.inner.borrow().is_some() + } /// Borrows the contents of this lazy cell for the duration of the cell /// itself. @@ -43,7 +45,7 @@ impl LazyCell { pub fn borrow(&self) -> Option<&T> { match *self.inner.borrow() { Some(ref inner) => unsafe { Some(mem::transmute(inner)) }, - None => None + None => None, } } diff --git a/src/util/mod.rs b/src/util/mod.rs index 866d1256111..f4abe88be61 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -14,7 +14,7 @@ use self::errors::NotFound; pub use self::errors::{CargoError, CargoResult, internal, human, internal_error}; pub use self::errors::{ChainError, std_error}; -pub use self::hasher::{HashingReader}; +pub use self::hasher::HashingReader; pub use self::head::Head; pub use self::io_util::{LimitErrorReader, read_le_u32, read_fill}; pub use self::lazy_cell::LazyCell; @@ -44,26 +44,24 @@ pub fn json_response(t: &T) -> Response { vec!["application/json; charset=utf-8".to_string()]); headers.insert("Content-Length".to_string(), vec![json.len().to_string()]); return Response { - status: (200, "OK"), - headers: headers, - body: Box::new(Cursor::new(json.into_bytes())), - }; + status: (200, "OK"), + headers: headers, + body: Box::new(Cursor::new(json.into_bytes())), + }; fn fixup(json: Json) -> Json { match json { Json::Object(object) => { - Json::Object(object.into_iter().map(|(k, v)| { - let k = if k == "krate" { - "crate".to_string() - } else { - k - }; - (k, fixup(v)) - }).collect()) - } - Json::Array(list) => { - Json::Array(list.into_iter().map(fixup).collect()) + Json::Object(object + .into_iter() + .map(|(k, v)| { + let k = + if k == "krate" { "crate".to_string() } else { k }; + (k, fixup(v)) + }) + .collect()) } + Json::Array(list) => Json::Array(list.into_iter().map(fixup).collect()), j => j, } } @@ -76,8 +74,7 @@ impl<'a> RequestUtils for Request + 'a { } fn query(&self) -> HashMap { - url::form_urlencoded::parse(self.query_string().unwrap_or("") - .as_bytes()) + url::form_urlencoded::parse(self.query_string().unwrap_or("").as_bytes()) .map(|(a, b)| (a.into_owned(), b.into_owned())) .collect() } @@ -93,22 +90,27 @@ impl<'a> RequestUtils for Request + 'a { } fn wants_json(&self) -> bool { - self.headers().find("Accept").map(|accept| { - accept.iter().any(|s| s.contains("json")) - }).unwrap_or(false) + self.headers() + .find("Accept") + .map(|accept| accept.iter().any(|s| s.contains("json"))) + .unwrap_or(false) } fn pagination(&self, default: usize, max: usize) -> CargoResult<(i64, i64)> { let query = self.query(); - let page = query.get("page").and_then(|s| s.parse::().ok()) - .unwrap_or(1); - let limit = query.get("per_page").and_then(|s| s.parse::().ok()) - .unwrap_or(default); + let page = query + .get("page") + .and_then(|s| s.parse::().ok()) + .unwrap_or(1); + let limit = query + .get("per_page") + .and_then(|s| s.parse::().ok()) + .unwrap_or(default); if limit > max { - return Err(human(&format_args!("cannot request more than {} items", max))) + return Err(human(&format_args!("cannot request more than {} items", max))); } if page == 0 { - return Err(human("page indexing starts from 1, page 0 is invalid")) + return Err(human("page indexing starts from 1, page 0 is invalid")); } Ok((((page - 1) * limit) as i64, limit as i64)) } @@ -117,7 +119,7 @@ impl<'a> RequestUtils for Request + 'a { pub struct C(pub fn(&mut Request) -> CargoResult); impl Handler for C { - fn call(&self, req: &mut Request) -> Result> { + fn call(&self, req: &mut Request) -> Result> { let C(f) = *self; match f(req) { Ok(resp) => { @@ -127,7 +129,7 @@ impl Handler for C { Err(e) => { match e.response() { Some(response) => Ok(response), - None => Err(std_error(e)) + None => Err(std_error(e)), } } } @@ -137,21 +139,21 @@ impl Handler for C { pub struct R(pub Arc); impl Handler for R { - fn call(&self, req: &mut Request) -> Result> { + fn call(&self, req: &mut Request) -> Result> { let path = req.params()["path"].to_string(); let R(ref sub_router) = *self; sub_router.call(&mut RequestProxy { - other: req, - path: Some(&path), - method: None, - }) + other: req, + path: Some(&path), + method: None, + }) } } pub struct R404(pub RouteBuilder); impl Handler for R404 { - fn call(&self, req: &mut Request) -> Result> { + fn call(&self, req: &mut Request) -> Result> { let R404(ref router) = *self; match router.recognize(&req.method(), req.path()) { Ok(m) => { diff --git a/src/util/request_proxy.rs b/src/util/request_proxy.rs index e29063abdd0..8c1929db133 100644 --- a/src/util/request_proxy.rs +++ b/src/util/request_proxy.rs @@ -19,10 +19,16 @@ impl<'a> Request for RequestProxy<'a> { self.other.conduit_version() } fn method(&self) -> conduit::Method { - self.method.clone().unwrap_or_else(|| self.other.method().clone()) + self.method + .clone() + .unwrap_or_else(|| self.other.method().clone()) + } + fn scheme(&self) -> conduit::Scheme { + self.other.scheme() + } + fn host(&self) -> conduit::Host { + self.other.host() } - fn scheme(&self) -> conduit::Scheme { self.other.scheme() } - fn host(&self) -> conduit::Host { self.other.host() } fn virtual_root(&self) -> Option<&str> { self.other.virtual_root() } @@ -32,14 +38,18 @@ impl<'a> Request for RequestProxy<'a> { fn query_string(&self) -> Option<&str> { self.other.query_string() } - fn remote_addr(&self) -> SocketAddr { self.other.remote_addr() } + fn remote_addr(&self) -> SocketAddr { + self.other.remote_addr() + } fn content_length(&self) -> Option { self.other.content_length() } fn headers(&self) -> &conduit::Headers { self.other.headers() } - fn body(&mut self) -> &mut Read { self.other.body() } + fn body(&mut self) -> &mut Read { + self.other.body() + } fn extensions(&self) -> &conduit::Extensions { self.other.extensions() } diff --git a/src/version.rs b/src/version.rs index 218d9b36b4b..8a37326f1b3 100644 --- a/src/version.rs +++ b/src/version.rs @@ -46,7 +46,7 @@ pub struct NewVersion { } pub struct Author { - pub name: String + pub name: String, } #[derive(RustcEncodable, RustcDecodable)] @@ -95,9 +95,10 @@ impl Version { VALUES ($1, $2, $3) \ RETURNING *")?; let rows = stmt.query(&[&crate_id, &num, &features])?; - let ret: Version = Model::from_row(&rows.iter().next().chain_error(|| { - internal("no version returned") - })?); + let ret: Version = + Model::from_row(&rows.iter() + .next() + .chain_error(|| internal("no version returned"))?); for author in authors { ret.add_author(conn, author)?; } @@ -109,8 +110,16 @@ impl Version { } pub fn encodable(self, crate_name: &str) -> EncodableVersion { - let Version { id, num, updated_at, created_at, - downloads, features, yanked, .. } = self; + let Version { + id, + num, + updated_at, + created_at, + downloads, + features, + yanked, + .. + } = self; let num = num.to_string(); EncodableVersion { dl_path: format!("/api/v1/crates/{}/{}/download", crate_name, num), @@ -133,8 +142,7 @@ impl Version { } /// Returns (dependency, crate dependency name) - pub fn dependencies(&self, conn: &PgConnection) - -> QueryResult> { + pub fn dependencies(&self, conn: &PgConnection) -> QueryResult> { Dependency::belonging_to(self) .inner_join(crates::table) .select((dependencies::all_columns, crates::name)) @@ -147,16 +155,15 @@ impl Version { WHERE version_id = $1 ORDER BY name ASC")?; let rows = stmt.query(&[&self.id])?; - Ok(rows.into_iter().map(|row| { - Author { name: row.get("name") } - }).collect()) + Ok(rows.into_iter() + .map(|row| Author { name: row.get("name") }) + .collect()) } - pub fn add_author(&self, - conn: &GenericConnection, - name: &str) -> CargoResult<()> { + pub fn add_author(&self, conn: &GenericConnection, name: &str) -> CargoResult<()> { conn.execute("INSERT INTO version_authors (version_id, name) - VALUES ($1, $2)", &[&self.id, &name])?; + VALUES ($1, $2)", + &[&self.id, &name])?; Ok(()) } @@ -166,33 +173,35 @@ impl Version { Ok(()) } - pub fn max(versions: T) -> semver::Version where - T: IntoIterator, + pub fn max(versions: T) -> semver::Version + where T: IntoIterator { - versions.into_iter() + versions + .into_iter() .max() - .unwrap_or_else(|| semver::Version { - major: 0, - minor: 0, - patch: 0, - pre: vec![], - build: vec![], + .unwrap_or_else(|| { + semver::Version { + major: 0, + minor: 0, + patch: 0, + pre: vec![], + build: vec![], + } }) } } impl NewVersion { - pub fn new( - crate_id: i32, - num: &semver::Version, - features: &HashMap>, - ) -> CargoResult { + pub fn new(crate_id: i32, + num: &semver::Version, + features: &HashMap>) + -> CargoResult { let features = json::encode(features)?; Ok(NewVersion { - crate_id: crate_id, - num: num.to_string(), - features: features, - }) + crate_id: crate_id, + num: num.to_string(), + features: features, + }) } pub fn save(&self, conn: &PgConnection, authors: &[String]) -> CargoResult { @@ -200,7 +209,8 @@ impl NewVersion { use diesel::expression::dsl::exists; use schema::versions::dsl::*; - let already_uploaded = versions.filter(crate_id.eq(self.crate_id)) + let already_uploaded = versions + .filter(crate_id.eq(self.crate_id)) .filter(num.eq(&self.num)); if select(exists(already_uploaded)).get_result(conn)? { return Err(human(&format_args!("crate version `{}` is already \ @@ -208,15 +218,20 @@ impl NewVersion { } conn.transaction(|| { - let version = insert(self).into(versions) - .get_result::(conn)?; - - let new_authors = authors.iter().map(|s| NewAuthor { - version_id: version.id, - name: &*s, - }).collect::>(); - - insert(&new_authors).into(version_authors::table) + let version = insert(self).into(versions).get_result::(conn)?; + + let new_authors = authors + .iter() + .map(|s| { + NewAuthor { + version_id: version.id, + name: &*s, + } + }) + .collect::>(); + + insert(&new_authors) + .into(version_authors::table) .execute(conn)?; Ok(version) }) @@ -234,9 +249,9 @@ impl Queryable for Version { type Row = (i32, i32, String, Timespec, Timespec, i32, Option, bool); fn build(row: Self::Row) -> Self { - let features = row.6.map(|s| { - json::decode(&s).unwrap() - }).unwrap_or_else(HashMap::new); + let features = row.6 + .map(|s| json::decode(&s).unwrap()) + .unwrap_or_else(HashMap::new); Version { id: row.0, crate_id: row.1, @@ -254,9 +269,9 @@ impl Model for Version { fn from_row(row: &Row) -> Version { let num: String = row.get("num"); let features: Option = row.get("features"); - let features = features.map(|s| { - json::decode(&s).unwrap() - }).unwrap_or_else(HashMap::new); + let features = features + .map(|s| json::decode(&s).unwrap()) + .unwrap_or_else(HashMap::new); Version { id: row.get("id"), crate_id: row.get("crate_id"), @@ -268,7 +283,9 @@ impl Model for Version { yanked: row.get("yanked"), } } - fn table_name(_: Option) -> &'static str { "versions" } + fn table_name(_: Option) -> &'static str { + "versions" + } } /// Handles the `GET /versions` route. @@ -277,15 +294,10 @@ pub fn index(req: &mut Request) -> CargoResult { let conn = req.tx()?; // Extract all ids requested. - let query = url::form_urlencoded::parse(req.query_string().unwrap_or("") - .as_bytes()); - let ids = query.filter_map(|(ref a, ref b)| { - if *a == "ids[]" { - b.parse().ok() - } else { - None - } - }).collect::>(); + let query = url::form_urlencoded::parse(req.query_string().unwrap_or("").as_bytes()); + let ids = query + .filter_map(|(ref a, ref b)| if *a == "ids[]" { b.parse().ok() } else { None }) + .collect::>(); // Load all versions // @@ -306,7 +318,9 @@ pub fn index(req: &mut Request) -> CargoResult { } #[derive(RustcEncodable)] - struct R { versions: Vec } + struct R { + versions: Vec, + } Ok(req.json(&R { versions: versions })) } @@ -318,7 +332,8 @@ pub fn show(req: &mut Request) -> CargoResult { let id = &req.params()["version_id"]; let id = id.parse().unwrap_or(0); let conn = req.db_conn()?; - versions::table.find(id) + versions::table + .find(id) .inner_join(crates::table) .select((versions::all_columns, ::krate::ALL_COLUMNS)) .first(&*conn)? @@ -326,23 +341,25 @@ pub fn show(req: &mut Request) -> CargoResult { }; #[derive(RustcEncodable)] - struct R { version: EncodableVersion } + struct R { + version: EncodableVersion, + } Ok(req.json(&R { version: version.encodable(&krate.name) })) } fn version_and_crate_old(req: &mut Request) -> CargoResult<(Version, Crate)> { let crate_name = &req.params()["crate_id"]; let semver = &req.params()["version"]; - let semver = semver::Version::parse(semver).map_err(|_| { - human(&format_args!("invalid semver: {}", semver)) - })?; + let semver = semver::Version::parse(semver) + .map_err(|_| human(&format_args!("invalid semver: {}", semver)))?; let tx = req.tx()?; let krate = Crate::find_by_name(tx, crate_name)?; let version = Version::find_by_num(tx, krate.id, &semver)?; - let version = version.chain_error(|| { - human(&format_args!("crate `{}` does not have a version `{}`", + let version = version + .chain_error(|| { + human(&format_args!("crate `{}` does not have a version `{}`", crate_name, semver)) - })?; + })?; Ok((version, krate)) } @@ -358,9 +375,9 @@ fn version_and_crate(req: &mut Request) -> CargoResult<(Version, Crate)> { .filter(versions::num.eq(semver)) .first(&*conn) .map_err(|_| { - human(&format_args!("crate `{}` does not have a version `{}`", + human(&format_args!("crate `{}` does not have a version `{}`", crate_name, semver)) - })?; + })?; Ok((version, krate)) } @@ -369,13 +386,15 @@ pub fn dependencies(req: &mut Request) -> CargoResult { let (version, _) = version_and_crate(req)?; let conn = req.db_conn()?; let deps = version.dependencies(&*conn)?; - let deps = deps.into_iter().map(|(dep, crate_name)| { - dep.encodable(&crate_name, None) - }).collect(); + let deps = deps.into_iter() + .map(|(dep, crate_name)| dep.encodable(&crate_name, None)) + .collect(); #[derive(RustcEncodable)] - struct R { dependencies: Vec } - Ok(req.json(&R{ dependencies: deps })) + struct R { + dependencies: Vec, + } + Ok(req.json(&R { dependencies: deps })) } /// Handles the `GET /crates/:crate_id/:version/downloads` route. @@ -383,9 +402,11 @@ pub fn downloads(req: &mut Request) -> CargoResult { use diesel::expression::dsl::date; let (version, _) = version_and_crate(req)?; let conn = req.db_conn()?; - let cutoff_end_date = req.query().get("before_date") + let cutoff_end_date = req.query() + .get("before_date") .and_then(|d| strptime(d, "%Y-%m-%d").ok()) - .unwrap_or_else(now_utc).to_timespec(); + .unwrap_or_else(now_utc) + .to_timespec(); let cutoff_start_date = cutoff_end_date + Duration::days(-89); let downloads = VersionDownload::belonging_to(&version) @@ -397,8 +418,10 @@ pub fn downloads(req: &mut Request) -> CargoResult { .collect(); #[derive(RustcEncodable)] - struct R { version_downloads: Vec } - Ok(req.json(&R{ version_downloads: downloads })) + struct R { + version_downloads: Vec, + } + Ok(req.json(&R { version_downloads: downloads })) } /// Handles the `GET /crates/:crate_id/:version/authors` route. @@ -411,10 +434,18 @@ pub fn authors(req: &mut Request) -> CargoResult { // This was never implemented. This complicated return struct // is all that is left, hear for backwards compatibility. #[derive(RustcEncodable)] - struct R { users: Vec<::user::EncodableUser>, meta: Meta } + struct R { + users: Vec<::user::EncodableUser>, + meta: Meta, + } #[derive(RustcEncodable)] - struct Meta { names: Vec } - Ok(req.json(&R{ users: vec![], meta: Meta { names: names } })) + struct Meta { + names: Vec, + } + Ok(req.json(&R { + users: vec![], + meta: Meta { names: names }, + })) } /// Handles the `DELETE /crates/:crate_id/:version/yank` route. @@ -433,19 +464,22 @@ fn modify_yank(req: &mut Request, yanked: bool) -> CargoResult { let conn = req.db_conn()?; let owners = krate.owners(&conn)?; if rights(req.app(), &owners, user)? < Rights::Publish { - return Err(human("must already be an owner to yank or unyank")) + return Err(human("must already be an owner to yank or unyank")); } if version.yanked != yanked { conn.transaction::<_, Box, _>(|| { - diesel::update(&version).set(versions::yanked.eq(yanked)) - .execute(&*conn)?; - git::yank(&**req.app(), &krate.name, &version.num, yanked)?; - Ok(()) - })?; + diesel::update(&version) + .set(versions::yanked.eq(yanked)) + .execute(&*conn)?; + git::yank(&**req.app(), &krate.name, &version.num, yanked)?; + Ok(()) + })?; } #[derive(RustcEncodable)] - struct R { ok: bool } - Ok(req.json(&R{ ok: true })) + struct R { + ok: bool, + } + Ok(req.json(&R { ok: true })) } From 23d1bc6280f6a28be2d855a5cb527948dc812baf Mon Sep 17 00:00:00 2001 From: Vignesh Date: Tue, 13 Jun 2017 13:33:18 +1000 Subject: [PATCH 02/14] Revert "cargo fmt" This reverts commit 74a0db975ffa40905b216b90dd773fcea4b7d36a. --- build.rs | 3 +- src/app.rs | 23 +- src/badge.rs | 60 ++-- src/bin/delete-crate.rs | 62 ++-- src/bin/delete-version.rs | 40 +-- src/bin/fill-in-user-id.rs | 23 +- src/bin/populate.rs | 8 +- src/bin/server.rs | 18 +- src/bin/transfer-crates.rs | 18 +- src/bin/update-downloads.rs | 217 ++++--------- src/categories.rs | 67 ++-- src/category.rs | 249 ++++++-------- src/db.rs | 52 ++- src/dependency.rs | 116 +++---- src/dist.rs | 22 +- src/download.rs | 18 +- src/git.rs | 65 ++-- src/http.rs | 34 +- src/keyword.rs | 71 ++-- src/krate.rs | 623 +++++++++++++++--------------------- src/lib.rs | 41 ++- src/owner.rs | 98 +++--- src/tests/all.rs | 215 ++++++------- src/tests/badge.rs | 240 ++++++++++---- src/tests/category.rs | 46 ++- src/tests/git.rs | 27 +- src/tests/keyword.rs | 20 +- src/tests/krate.rs | 388 +++++++++------------- src/tests/record.rs | 173 +++++----- src/tests/team.rs | 170 +++++----- src/tests/user.rs | 63 ++-- src/tests/version.rs | 11 +- src/upload.rs | 58 ++-- src/uploaders.rs | 86 ++--- src/user/middleware.rs | 14 +- src/user/mod.rs | 153 ++++----- src/util/errors.rs | 179 ++++------- src/util/head.rs | 18 +- src/util/io_util.rs | 14 +- src/util/lazy_cell.rs | 6 +- src/util/mod.rs | 72 ++--- src/util/request_proxy.rs | 20 +- src/version.rs | 214 ++++++------- 43 files changed, 1740 insertions(+), 2375 deletions(-) diff --git a/build.rs b/build.rs index d72b5441d7c..70c9bb1d8e4 100644 --- a/build.rs +++ b/build.rs @@ -13,7 +13,8 @@ fn main() { if let Ok(database_url) = env::var("TEST_DATABASE_URL") { let connection = PgConnection::establish(&database_url) .expect("Could not connect to TEST_DATABASE_URL"); - run_pending_migrations(&connection).expect("Error running migrations"); + run_pending_migrations(&connection) + .expect("Error running migrations"); } } } diff --git a/src/app.rs b/src/app.rs index acaff6fd17a..b38ee8412a1 100644 --- a/src/app.rs +++ b/src/app.rs @@ -34,15 +34,17 @@ pub struct App { /// The `AppMiddleware` injects an `App` instance into the `Request` extensions pub struct AppMiddleware { - app: Arc, + app: Arc } impl App { pub fn new(config: &Config) -> App { - let mut github = oauth2::Config::new(&config.gh_client_id, - &config.gh_client_secret, - "https://github.com/login/oauth/authorize", - "https://github.com/login/oauth/access_token"); + let mut github = oauth2::Config::new( + &config.gh_client_id, + &config.gh_client_secret, + "https://github.com/login/oauth/authorize", + "https://github.com/login/oauth/access_token", + ); github.scopes.push(String::from("read:org")); @@ -103,15 +105,13 @@ impl AppMiddleware { } impl Middleware for AppMiddleware { - fn before(&self, req: &mut Request) -> Result<(), Box> { + fn before(&self, req: &mut Request) -> Result<(), Box> { req.mut_extensions().insert(self.app.clone()); Ok(()) } - fn after(&self, - req: &mut Request, - res: Result>) - -> Result> { + fn after(&self, req: &mut Request, res: Result>) + -> Result> { req.mut_extensions().pop::>().unwrap(); res } @@ -124,6 +124,7 @@ pub trait RequestApp { impl RequestApp for T { fn app(&self) -> &Arc { - self.extensions().find::>().expect("Missing app") + self.extensions().find::>() + .expect("Missing app") } } diff --git a/src/badge.rs b/src/badge.rs index 82bc0f64923..bcb627b32ed 100644 --- a/src/badge.rs +++ b/src/badge.rs @@ -12,35 +12,31 @@ use std::collections::HashMap; pub enum Badge { #[serde(rename = "travis-ci")] TravisCi { - repository: String, - branch: Option, + repository: String, branch: Option, }, #[serde(rename = "appveyor")] Appveyor { - repository: String, - branch: Option, - service: Option, + repository: String, branch: Option, service: Option, }, #[serde(rename = "gitlab")] GitLab { - repository: String, - branch: Option, + repository: String, branch: Option, }, #[serde(rename = "is-it-maintained-issue-resolution")] - IsItMaintainedIssueResolution { repository: String }, + IsItMaintainedIssueResolution { + repository: String, + }, #[serde(rename = "is-it-maintained-open-issues")] - IsItMaintainedOpenIssues { repository: String }, + IsItMaintainedOpenIssues { + repository: String, + }, #[serde(rename = "codecov")] Codecov { - repository: String, - branch: Option, - service: Option, + repository: String, branch: Option, service: Option, }, #[serde(rename = "coveralls")] Coveralls { - repository: String, - branch: Option, - service: Option, + repository: String, branch: Option, service: Option, }, } @@ -55,7 +51,8 @@ impl Queryable for Badge { fn build((_, badge_type, attributes): Self::Row) -> Self { let json = json!({"badge_type": badge_type, "attributes": attributes}); - serde_json::from_value(json).expect("Invalid CI badge in the database") + serde_json::from_value(json) + .expect("Invalid CI badge in the database") } } @@ -66,13 +63,13 @@ impl Badge { pub fn badge_type(&self) -> &'static str { match *self { - Badge::TravisCi { .. } => "travis-ci", - Badge::Appveyor { .. } => "appveyor", - Badge::GitLab { .. } => "gitlab", - Badge::IsItMaintainedIssueResolution { .. } => "is-it-maintained-issue-resolution", - Badge::IsItMaintainedOpenIssues { .. } => "is-it-maintained-open-issues", - Badge::Codecov { .. } => "codecov", - Badge::Coveralls { .. } => "coveralls", + Badge::TravisCi {..} => "travis-ci", + Badge::Appveyor {..} => "appveyor", + Badge::GitLab{..} => "gitlab", + Badge::IsItMaintainedIssueResolution{..} => "is-it-maintained-issue-resolution", + Badge::IsItMaintainedOpenIssues{..} => "is-it-maintained-open-issues", + Badge::Codecov{..} => "codecov", + Badge::Coveralls{..} => "coveralls", } } @@ -100,10 +97,10 @@ impl Badge { let json = json!({"badge_type": k, "attributes": attributes_json}); if serde_json::from_value::(json).is_ok() { new_badges.push(NewBadge { - crate_id: krate.id, - badge_type: &**k, - attributes: attributes_json, - }); + crate_id: krate.id, + badge_type: &**k, + attributes: attributes_json, + }); } else { invalid_badges.push(&**k); } @@ -111,10 +108,9 @@ impl Badge { } conn.transaction(|| { - delete(badges::table.filter(badges::crate_id.eq(krate.id))) - .execute(conn)?; - insert(&new_badges).into(badges::table).execute(conn)?; - Ok(invalid_badges) - }) + delete(badges::table.filter(badges::crate_id.eq(krate.id))).execute(conn)?; + insert(&new_badges).into(badges::table).execute(conn)?; + Ok(invalid_badges) + }) } } diff --git a/src/bin/delete-crate.rs b/src/bin/delete-crate.rs index 996bac59c7d..3c15bc99204 100644 --- a/src/bin/delete-crate.rs +++ b/src/bin/delete-crate.rs @@ -30,96 +30,80 @@ fn main() { fn delete(tx: &postgres::transaction::Transaction) { let name = match env::args().nth(1) { - None => { - println!("needs a crate-name argument"); - return; - } + None => { println!("needs a crate-name argument"); return } Some(s) => s, }; let krate = Crate::find_by_name(tx, &name).unwrap(); - print!("Are you sure you want to delete {} ({}) [y/N]: ", - name, - krate.id); + print!("Are you sure you want to delete {} ({}) [y/N]: ", name, krate.id); io::stdout().flush().unwrap(); let mut line = String::new(); io::stdin().read_line(&mut line).unwrap(); - if !line.starts_with("y") { - return; - } + if !line.starts_with("y") { return } let versions = krate.versions(tx).unwrap(); for v in versions.iter() { println!("deleting version {} ({})", v.num, v.id); let n = tx.execute("DELETE FROM version_downloads WHERE version_id = $1", - &[&v.id]) - .unwrap(); + &[&v.id]).unwrap(); println!(" {} download records deleted", n); let n = tx.execute("DELETE FROM version_authors WHERE version_id = $1", - &[&v.id]) - .unwrap(); + &[&v.id]).unwrap(); println!(" {} author records deleted", n); - let n = tx.execute("DELETE FROM dependencies WHERE version_id = $1", &[&v.id]) - .unwrap(); + let n = tx.execute("DELETE FROM dependencies WHERE version_id = $1", + &[&v.id]).unwrap(); println!(" {} dependencies deleted", n); - tx.execute("DELETE FROM versions WHERE id = $1", &[&v.id]) - .unwrap(); + tx.execute("DELETE FROM versions WHERE id = $1", + &[&v.id]).unwrap(); } println!("deleting follows"); - let n = tx.execute("DELETE FROM follows WHERE crate_id = $1", &[&krate.id]) - .unwrap(); + let n = tx.execute("DELETE FROM follows WHERE crate_id = $1", + &[&krate.id]).unwrap(); println!(" {} deleted", n); println!("deleting crate download records"); let n = tx.execute("DELETE FROM crate_downloads WHERE crate_id = $1", - &[&krate.id]) - .unwrap(); + &[&krate.id]).unwrap(); println!(" {} deleted", n); println!("deleting crate owners"); - let n = tx.execute("DELETE FROM crate_owners WHERE crate_id = $1", &[&krate.id]) - .unwrap(); + let n = tx.execute("DELETE FROM crate_owners WHERE crate_id = $1", + &[&krate.id]).unwrap(); println!(" {} deleted", n); println!("disabling reserved crate name trigger"); let _ = tx.execute("ALTER TABLE crates DISABLE TRIGGER trigger_ensure_crate_name_not_reserved;", - &[]) - .unwrap(); + &[]).unwrap(); println!("deleting crate keyword connections"); let n = tx.execute("DELETE FROM crates_keywords WHERE crate_id = $1", - &[&krate.id]) - .unwrap(); + &[&krate.id]).unwrap(); println!(" {} deleted", n); println!("deleting crate category connections"); let n = tx.execute("DELETE FROM crates_categories WHERE crate_id = $1", - &[&krate.id]) - .unwrap(); + &[&krate.id]).unwrap(); println!(" {} deleted", n); println!("enabling reserved crate name trigger"); let _ = tx.execute("ALTER TABLE crates ENABLE TRIGGER trigger_ensure_crate_name_not_reserved;", - &[]) - .unwrap(); + &[]).unwrap(); println!("deleting crate badges"); - let n = tx.execute("DELETE FROM badges WHERE crate_id = $1", &[&krate.id]) - .unwrap(); + let n = tx.execute("DELETE FROM badges WHERE crate_id = $1", + &[&krate.id]).unwrap(); println!(" {} deleted", n); println!("deleting the crate"); - let n = tx.execute("DELETE FROM crates WHERE id = $1", &[&krate.id]) - .unwrap(); + let n = tx.execute("DELETE FROM crates WHERE id = $1", + &[&krate.id]).unwrap(); println!(" {} deleted", n); print!("commit? [y/N]: "); io::stdout().flush().unwrap(); let mut line = String::new(); io::stdin().read_line(&mut line).unwrap(); - if !line.starts_with("y") { - panic!("aborting transaction"); - } + if !line.starts_with("y") { panic!("aborting transaction"); } } diff --git a/src/bin/delete-version.rs b/src/bin/delete-version.rs index 55c5b02d75c..c3711175146 100644 --- a/src/bin/delete-version.rs +++ b/src/bin/delete-version.rs @@ -31,56 +31,40 @@ fn main() { fn delete(tx: &postgres::transaction::Transaction) { let name = match env::args().nth(1) { - None => { - println!("needs a crate-name argument"); - return; - } + None => { println!("needs a crate-name argument"); return } Some(s) => s, }; let version = match env::args().nth(2) { - None => { - println!("needs a version argument"); - return; - } + None => { println!("needs a version argument"); return } Some(s) => s, }; let version = semver::Version::parse(&version).unwrap(); let krate = Crate::find_by_name(tx, &name).unwrap(); - let v = Version::find_by_num(tx, krate.id, &version) - .unwrap() - .unwrap(); - print!("Are you sure you want to delete {}#{} ({}) [y/N]: ", - name, - version, + let v = Version::find_by_num(tx, krate.id, &version).unwrap().unwrap(); + print!("Are you sure you want to delete {}#{} ({}) [y/N]: ", name, version, v.id); io::stdout().flush().unwrap(); let mut line = String::new(); io::stdin().read_line(&mut line).unwrap(); - if !line.starts_with("y") { - return; - } + if !line.starts_with("y") { return } println!("deleting version {} ({})", v.num, v.id); let n = tx.execute("DELETE FROM version_downloads WHERE version_id = $1", - &[&v.id]) - .unwrap(); + &[&v.id]).unwrap(); println!(" {} download records deleted", n); let n = tx.execute("DELETE FROM version_authors WHERE version_id = $1", - &[&v.id]) - .unwrap(); + &[&v.id]).unwrap(); println!(" {} author records deleted", n); - let n = tx.execute("DELETE FROM dependencies WHERE version_id = $1", &[&v.id]) - .unwrap(); + let n = tx.execute("DELETE FROM dependencies WHERE version_id = $1", + &[&v.id]).unwrap(); println!(" {} dependencies deleted", n); - tx.execute("DELETE FROM versions WHERE id = $1", &[&v.id]) - .unwrap(); + tx.execute("DELETE FROM versions WHERE id = $1", + &[&v.id]).unwrap(); print!("commit? [y/N]: "); io::stdout().flush().unwrap(); let mut line = String::new(); io::stdin().read_line(&mut line).unwrap(); - if !line.starts_with("y") { - panic!("aborting transaction"); - } + if !line.starts_with("y") { panic!("aborting transaction"); } } diff --git a/src/bin/fill-in-user-id.rs b/src/bin/fill-in-user-id.rs index 1fa69ad6961..e1dfae7442d 100644 --- a/src/bin/fill-in-user-id.rs +++ b/src/bin/fill-in-user-id.rs @@ -53,17 +53,13 @@ struct GithubUser { fn update(app: &App, tx: &postgres::transaction::Transaction) { let query = "SELECT id, gh_login, gh_access_token, gh_avatar FROM users WHERE gh_id IS NULL"; - let rows = tx.query(query, &[]) - .unwrap() - .into_iter() - .map(|row| { - let id: i32 = row.get("id"); - let login: String = row.get("gh_login"); - let token: String = row.get("gh_access_token"); - let avatar: Option = row.get("gh_avatar"); - (id, login, http::token(token), avatar) - }) - .collect::>(); + let rows = tx.query(query, &[]).unwrap().into_iter().map(|row| { + let id: i32 = row.get("id"); + let login: String = row.get("gh_login"); + let token: String = row.get("gh_access_token"); + let avatar: Option = row.get("gh_avatar"); + (id, login, http::token(token), avatar) + }).collect::>(); for (id, login, token, avatar) in rows { println!("attempt: {}/{}", id, login); @@ -73,12 +69,12 @@ fn update(app: &App, tx: &postgres::transaction::Transaction) { let ghuser: GithubUser = http::parse_github_response(handle, &resp)?; if let Some(ref avatar) = avatar { if !avatar.contains(&ghuser.id.to_string()) { - return Err(human(&format_args!("avatar: {}", avatar))); + return Err(human(&format_args!("avatar: {}", avatar))) } } if ghuser.login == login { tx.execute("UPDATE users SET gh_id = $1 WHERE id = $2", - &[&ghuser.id, &id])?; + &[&ghuser.id, &id])?; Ok(()) } else { Err(human(&format_args!("different login: {}", ghuser.login))) @@ -89,3 +85,4 @@ fn update(app: &App, tx: &postgres::transaction::Transaction) { } } } + diff --git a/src/bin/populate.rs b/src/bin/populate.rs index 29ba6caf18a..b4567d6c367 100644 --- a/src/bin/populate.rs +++ b/src/bin/populate.rs @@ -27,9 +27,9 @@ fn main() { } fn update(tx: &postgres::transaction::Transaction) -> postgres::Result<()> { - let ids = env::args() - .skip(1) - .filter_map(|arg| arg.parse::().ok()); + let ids = env::args().skip(1).filter_map(|arg| { + arg.parse::().ok() + }); for id in ids { let now = time::now_utc().to_timespec(); let mut rng = StdRng::new().unwrap(); @@ -41,7 +41,7 @@ fn update(tx: &postgres::transaction::Transaction) -> postgres::Result<()> { tx.execute("INSERT INTO version_downloads \ (version_id, downloads, date) \ VALUES ($1, $2, $3)", - &[&id, &dls, &moment])?; + &[&id, &dls, &moment])?; } } Ok(()) diff --git a/src/bin/server.rs b/src/bin/server.rs index 7109339b5d3..daadf46a9f7 100644 --- a/src/bin/server.rs +++ b/src/bin/server.rs @@ -31,9 +31,8 @@ fn main() { let mut opts = git2::FetchOptions::new(); opts.remote_callbacks(cb); git2::build::RepoBuilder::new() - .fetch_options(opts) - .clone(&url, &checkout) - .unwrap() + .fetch_options(opts) + .clone(&url, &checkout).unwrap() } }; let mut cfg = repo.config().unwrap(); @@ -65,7 +64,7 @@ fn main() { &api_protocol), proxy: None, } - } + }, (Env::Production, Replica::ReadOnlyMirror) => { // Read-only mirrors don't need access key or secret key, // but they might have them. Definitely need bucket though. @@ -77,7 +76,7 @@ fn main() { &api_protocol), proxy: None, } - } + }, _ => { if env::var("S3_BUCKET").is_ok() { println!("Using S3 uploader"); @@ -93,7 +92,7 @@ fn main() { println!("Using local uploader, crate files will be in the dist directory"); Uploader::Local } - } + }, }; let config = cargo_registry::Config { @@ -116,12 +115,9 @@ fn main() { let port = if heroku { 8888 } else { - env::var("PORT") - .ok() - .and_then(|s| s.parse().ok()) - .unwrap_or(8888) + env::var("PORT").ok().and_then(|s| s.parse().ok()).unwrap_or(8888) }; - let threads = if cargo_env == Env::Development { 1 } else { 50 }; + let threads = if cargo_env == Env::Development {1} else {50}; let mut cfg = civet::Config::new(); cfg.port(port).threads(threads).keep_alive(true); let _a = Server::start(cfg, app); diff --git a/src/bin/transfer-crates.rs b/src/bin/transfer-crates.rs index 01539b4fc98..817a1943d3f 100644 --- a/src/bin/transfer-crates.rs +++ b/src/bin/transfer-crates.rs @@ -31,17 +31,11 @@ fn main() { fn transfer(tx: &postgres::transaction::Transaction) { let from = match env::args().nth(1) { - None => { - println!("needs a from-user argument"); - return; - } + None => { println!("needs a from-user argument"); return } Some(s) => s, }; let to = match env::args().nth(2) { - None => { - println!("needs a to-user argument"); - return; - } + None => { println!("needs a to-user argument"); return } Some(s) => s, }; @@ -61,15 +55,14 @@ fn transfer(tx: &postgres::transaction::Transaction) { } println!("Are you sure you want to transfer crates from {} to {}", - from.gh_login, - to.gh_login); + from.gh_login, to.gh_login); get_confirm("continue"); let stmt = tx.prepare("SELECT * FROM crate_owners WHERE owner_id = $1 AND owner_kind = $2") - .unwrap(); + .unwrap(); let rows = stmt.query(&[&from.id, &(OwnerKind::User as i32)]).unwrap(); for row in rows.iter() { let id: i32 = row.get("id"); @@ -81,8 +74,7 @@ fn transfer(tx: &postgres::transaction::Transaction) { } let n = tx.execute("UPDATE crate_owners SET owner_id = $1 WHERE id $2", - &[&to.id, &id]) - .unwrap(); + &[&to.id, &id]).unwrap(); assert_eq!(n, 1); } diff --git a/src/bin/update-downloads.rs b/src/bin/update-downloads.rs index 4aaa25bc0d4..299d97558aa 100644 --- a/src/bin/update-downloads.rs +++ b/src/bin/update-downloads.rs @@ -17,7 +17,8 @@ static LIMIT: i64 = 1000; #[allow(dead_code)] // dead in tests fn main() { - let daemon = env::args().nth(1).as_ref().map(|s| &s[..]) == Some("daemon"); + let daemon = env::args().nth(1).as_ref().map(|s| &s[..]) + == Some("daemon"); let sleep = env::args().nth(2).map(|s| s.parse().unwrap()); loop { let conn = cargo_registry::db::connect_now(); @@ -26,7 +27,7 @@ fn main() { if daemon { std::thread::sleep(Duration::new(sleep.unwrap(), 0)); } else { - break; + break } } } @@ -36,8 +37,7 @@ fn update(conn: &postgres::GenericConnection) -> postgres::Result<()> { loop { // FIXME(rust-lang/rust#27401): weird declaration to make sure this // variable gets dropped. - let tx; - tx = conn.transaction()?; + let tx; tx = conn.transaction()?; { let stmt = tx.prepare("SELECT * FROM version_downloads \ WHERE processed = FALSE AND id > $1 @@ -56,8 +56,7 @@ fn update(conn: &postgres::GenericConnection) -> postgres::Result<()> { } fn collect(tx: &postgres::transaction::Transaction, - rows: &mut postgres::rows::Rows) - -> postgres::Result> { + rows: &mut postgres::rows::Rows) -> postgres::Result> { // Anything older than 24 hours ago will be frozen and will not be queried // against again. let now = chrono::UTC::now(); @@ -68,11 +67,9 @@ fn collect(tx: &postgres::transaction::Transaction, let download: VersionDownload = Model::from_row(&row); assert!(map.insert(download.id, download).is_none()); } - println!("updating {} versions (cutoff {})", - map.len(), - now.to_rfc2822()); + println!("updating {} versions (cutoff {})", map.len(), now.to_rfc2822()); if map.len() == 0 { - return Ok(None); + return Ok(None) } let mut max = 0; @@ -82,7 +79,7 @@ fn collect(tx: &postgres::transaction::Transaction, max = *id; } if download.date > cutoff && download.counted == download.downloads { - continue; + continue } let amt = download.downloads - download.counted; @@ -91,11 +88,11 @@ fn collect(tx: &postgres::transaction::Transaction, tx.execute("UPDATE version_downloads SET processed = $2, counted = counted + $3 WHERE id = $1", - &[id, &(download.date < cutoff), &amt])?; + &[id, &(download.date < cutoff), &amt])?; total += amt as i64; if amt == 0 { - continue; + continue } let crate_id = Version::find(tx, download.version_id).unwrap().crate_id; @@ -104,11 +101,10 @@ fn collect(tx: &postgres::transaction::Transaction, tx.execute("UPDATE versions SET downloads = downloads + $1 WHERE id = $2", - &[&amt, &download.version_id])?; + &[&amt, &download.version_id])?; // Update the total number of crate downloads tx.execute("UPDATE crates SET downloads = downloads + $1 - WHERE id = $2", - &[&amt, &crate_id])?; + WHERE id = $2", &[&amt, &crate_id])?; // Update the total number of crate downloads for today let cnt = tx.execute("UPDATE crate_downloads @@ -119,14 +115,14 @@ fn collect(tx: &postgres::transaction::Transaction, tx.execute("INSERT INTO crate_downloads (crate_id, downloads, date) VALUES ($1, $2, $3)", - &[&crate_id, &amt, &download.date])?; + &[&crate_id, &amt, &download.date])?; } } // After everything else is done, update the global counter of total // downloads. tx.execute("UPDATE metadata SET total_downloads = total_downloads + $1", - &[&total])?; + &[&total])?; Ok(Some(max)) } @@ -144,24 +140,20 @@ mod test { use cargo_registry::{Version, Crate, User, Model, env}; fn conn() -> postgres::Connection { - postgres::Connection::connect(&env("TEST_DATABASE_URL")[..], postgres::TlsMode::None) - .unwrap() + postgres::Connection::connect(&env("TEST_DATABASE_URL")[..], + postgres::TlsMode::None).unwrap() } - fn user(conn: &postgres::transaction::Transaction) -> User { - User::find_or_insert(conn, 2, "login", None, None, None, "access_token").unwrap() + fn user(conn: &postgres::transaction::Transaction) -> User{ + User::find_or_insert(conn, 2, "login", None, None, None, + "access_token").unwrap() } fn crate_downloads(tx: &postgres::transaction::Transaction, id: i32, expected: usize) { let stmt = tx.prepare("SELECT * FROM crate_downloads - WHERE crate_id = $1") - .unwrap(); - let dl: i32 = stmt.query(&[&id]) - .unwrap() - .iter() - .next() - .unwrap() - .get("downloads"); + WHERE crate_id = $1").unwrap(); + let dl: i32 = stmt.query(&[&id]).unwrap().iter() + .next().unwrap().get("downloads"); assert_eq!(dl, expected as i32); } @@ -170,34 +162,20 @@ mod test { let conn = conn(); let tx = conn.transaction().unwrap(); let user = user(&tx); - let krate = Crate::find_or_insert(&tx, - "foo", - user.id, - &None, - &None, - &None, - &None, - &None, - &None, - &None, - None) - .unwrap(); - let version = Version::insert(&tx, - krate.id, + let krate = Crate::find_or_insert(&tx, "foo", user.id, &None, &None, + &None, &None, &None, &None, + &None, None).unwrap(); + let version = Version::insert(&tx, krate.id, &semver::Version::parse("1.0.0").unwrap(), - &HashMap::new(), - &[]) - .unwrap(); + &HashMap::new(), &[]).unwrap(); tx.execute("INSERT INTO version_downloads \ (version_id) VALUES ($1)", - &[&version.id]) - .unwrap(); + &[&version.id]).unwrap(); tx.execute("INSERT INTO version_downloads \ (version_id, date, processed) VALUES ($1, current_date - interval '1 day', true)", - &[&version.id]) - .unwrap(); + &[&version.id]).unwrap(); ::update(&tx).unwrap(); assert_eq!(Version::find(&tx, version.id).unwrap().downloads, 1); assert_eq!(Crate::find(&tx, krate.id).unwrap().downloads, 1); @@ -211,39 +189,21 @@ mod test { let conn = conn(); let tx = conn.transaction().unwrap(); let user = user(&tx); - let krate = Crate::find_or_insert(&tx, - "foo", - user.id, - &None, - &None, - &None, - &None, - &None, - &None, - &None, - None) - .unwrap(); - let version = Version::insert(&tx, - krate.id, + let krate = Crate::find_or_insert(&tx, "foo", user.id, &None, + &None, &None, &None, &None, + &None, &None, None).unwrap(); + let version = Version::insert(&tx, krate.id, &semver::Version::parse("1.0.0").unwrap(), - &HashMap::new(), - &[]) - .unwrap(); + &HashMap::new(), &[]).unwrap(); tx.execute("INSERT INTO version_downloads \ (version_id, downloads, counted, date, processed) VALUES ($1, 2, 2, current_date - interval '2 days', false)", - &[&version.id]) - .unwrap(); + &[&version.id]).unwrap(); ::update(&tx).unwrap(); let stmt = tx.prepare("SELECT processed FROM version_downloads - WHERE version_id = $1") - .unwrap(); - let processed: bool = stmt.query(&[&version.id]) - .unwrap() - .iter() - .next() - .unwrap() - .get("processed"); + WHERE version_id = $1").unwrap(); + let processed: bool = stmt.query(&[&version.id]).unwrap().iter() + .next().unwrap().get("processed"); assert!(processed); } @@ -252,40 +212,22 @@ mod test { let conn = conn(); let tx = conn.transaction().unwrap(); let user = user(&tx); - let krate = Crate::find_or_insert(&tx, - "foo", - user.id, - &None, - &None, - &None, - &None, - &None, - &None, - &None, - None) - .unwrap(); - let version = Version::insert(&tx, - krate.id, + let krate = Crate::find_or_insert(&tx, "foo", user.id, &None, + &None, &None, &None, &None, + &None, &None, None).unwrap(); + let version = Version::insert(&tx, krate.id, &semver::Version::parse("1.0.0").unwrap(), - &HashMap::new(), - &[]) - .unwrap(); + &HashMap::new(), &[]).unwrap(); let time = time::now_utc().to_timespec() - Duration::hours(2); tx.execute("INSERT INTO version_downloads \ (version_id, downloads, counted, date, processed) VALUES ($1, 2, 2, date($2), false)", - &[&version.id, &time]) - .unwrap(); + &[&version.id, &time]).unwrap(); ::update(&tx).unwrap(); let stmt = tx.prepare("SELECT processed FROM version_downloads - WHERE version_id = $1") - .unwrap(); - let processed: bool = stmt.query(&[&version.id]) - .unwrap() - .iter() - .next() - .unwrap() - .get("processed"); + WHERE version_id = $1").unwrap(); + let processed: bool = stmt.query(&[&version.id]).unwrap().iter() + .next().unwrap().get("processed"); assert!(!processed); } @@ -294,42 +236,26 @@ mod test { let conn = conn(); let tx = conn.transaction().unwrap(); let user = user(&tx); - let krate = Crate::find_or_insert(&tx, - "foo", - user.id, - &None, - &None, - &None, - &None, - &None, - &None, - &None, - None) - .unwrap(); - let version = Version::insert(&tx, - krate.id, + let krate = Crate::find_or_insert(&tx, "foo", user.id, &None, + &None, &None, &None, &None, + &None, &None, None).unwrap(); + let version = Version::insert(&tx, krate.id, &semver::Version::parse("1.0.0").unwrap(), - &HashMap::new(), - &[]) - .unwrap(); + &HashMap::new(), &[]).unwrap(); tx.execute("UPDATE versions SET updated_at = current_date - interval '2 hours'", - &[]) - .unwrap(); + &[]).unwrap(); tx.execute("UPDATE crates SET updated_at = current_date - interval '2 hours'", - &[]) - .unwrap(); + &[]).unwrap(); tx.execute("INSERT INTO version_downloads \ (version_id, downloads, counted, date, processed) VALUES ($1, 2, 1, current_date, false)", - &[&version.id]) - .unwrap(); + &[&version.id]).unwrap(); tx.execute("INSERT INTO version_downloads \ (version_id, date) VALUES ($1, current_date - interval '1 day')", - &[&version.id]) - .unwrap(); + &[&version.id]).unwrap(); let version_before = Version::find(&tx, version.id).unwrap(); let krate_before = Crate::find(&tx, krate.id).unwrap(); @@ -350,37 +276,22 @@ mod test { let conn = conn(); let tx = conn.transaction().unwrap(); let user = user(&tx); - let krate = Crate::find_or_insert(&tx, - "foo", - user.id, - &None, - &None, - &None, - &None, - &None, - &None, - &None, - None) - .unwrap(); - let version = Version::insert(&tx, - krate.id, + let krate = Crate::find_or_insert(&tx, "foo", user.id, &None, + &None, &None, &None, &None, + &None, &None, None).unwrap(); + let version = Version::insert(&tx, krate.id, &semver::Version::parse("1.0.0").unwrap(), - &HashMap::new(), - &[]) - .unwrap(); + &HashMap::new(), &[]).unwrap(); tx.execute("UPDATE versions SET updated_at = current_date - interval '2 days'", - &[]) - .unwrap(); + &[]).unwrap(); tx.execute("UPDATE crates SET updated_at = current_date - interval '2 days'", - &[]) - .unwrap(); + &[]).unwrap(); tx.execute("INSERT INTO version_downloads \ (version_id, downloads, counted, date, processed) VALUES ($1, 2, 2, current_date - interval '2 days', false)", - &[&version.id]) - .unwrap(); + &[&version.id]).unwrap(); let version_before = Version::find(&tx, version.id).unwrap(); let krate_before = Crate::find(&tx, krate.id).unwrap(); diff --git a/src/categories.rs b/src/categories.rs index c927351367c..6cb41b05669 100644 --- a/src/categories.rs +++ b/src/categories.rs @@ -13,10 +13,7 @@ struct Category { } impl Category { - fn from_parent(slug: &str, - name: &str, - description: &str, - parent: Option<&Category>) + fn from_parent(slug: &str, name: &str, description: &str, parent: Option<&Category>) -> Category { match parent { Some(parent) => { @@ -46,33 +43,34 @@ fn required_string_from_toml<'a>(toml: &'a toml::Table, key: &str) -> CargoResul } fn optional_string_from_toml<'a>(toml: &'a toml::Table, key: &str) -> &'a str { - toml.get(key).and_then(toml::Value::as_str).unwrap_or("") + toml.get(key) + .and_then(toml::Value::as_str) + .unwrap_or("") } -fn categories_from_toml(categories: &toml::Table, - parent: Option<&Category>) - -> CargoResult> { +fn categories_from_toml(categories: &toml::Table, parent: Option<&Category>) -> CargoResult> { let mut result = vec![]; for (slug, details) in categories { - let details = - details - .as_table() - .chain_error(|| internal(&format_args!("category {} was not a TOML table", slug)))?; + let details = details.as_table().chain_error(|| { + internal(&format_args!("category {} was not a TOML table", slug)) + })?; - let category = Category::from_parent(slug, - required_string_from_toml(details, "name")?, - optional_string_from_toml(details, "description"), - parent); + let category = Category::from_parent( + slug, + required_string_from_toml(details, "name")?, + optional_string_from_toml(details, "description"), + parent, + ); if let Some(categories) = details.get("categories") { - let categories = categories - .as_table() - .chain_error(|| { - internal(&format_args!("child categories of {} were not a table", slug)) - })?; + let categories = categories.as_table().chain_error(|| { + internal(&format_args!("child categories of {} were not a table", slug)) + })?; - result.extend(categories_from_toml(categories, Some(&category))?); + result.extend( + categories_from_toml(categories, Some(&category))? + ); } result.push(category) @@ -86,12 +84,13 @@ pub fn sync() -> CargoResult<()> { let tx = conn.transaction().unwrap(); let categories = include_str!("./categories.toml"); - let toml = toml::Parser::new(categories) - .parse() - .expect("Could not parse categories.toml"); + let toml = toml::Parser::new(categories).parse().expect( + "Could not parse categories.toml" + ); - let categories = categories_from_toml(&toml, None) - .expect("Could not convert categories from TOML"); + let categories = categories_from_toml(&toml, None).expect( + "Could not convert categories from TOML" + ); for category in &categories { tx.execute("\ @@ -100,20 +99,20 @@ pub fn sync() -> CargoResult<()> { ON CONFLICT (slug) DO UPDATE \ SET category = EXCLUDED.category, \ description = EXCLUDED.description;", - &[&category.slug, &category.name, &category.description])?; + &[&category.slug, &category.name, &category.description] + )?; } - let in_clause = categories - .iter() - .map(|category| format!("LOWER('{}')", category.slug)) - .collect::>() - .join(","); + let in_clause = categories.iter().map(|category| { + format!("LOWER('{}')", category.slug) + }).collect::>().join(","); tx.execute(&format!("\ DELETE FROM categories \ WHERE slug NOT IN ({});", in_clause), - &[])?; + &[] + )?; tx.set_commit(); tx.finish().unwrap(); Ok(()) diff --git a/src/category.rs b/src/category.rs index 70f14899523..f6f45cb2188 100644 --- a/src/category.rs +++ b/src/category.rs @@ -57,34 +57,29 @@ pub struct EncodableCategoryWithSubcategories { } impl Category { - pub fn find_by_category(conn: &GenericConnection, name: &str) -> CargoResult { + pub fn find_by_category(conn: &GenericConnection, name: &str) + -> CargoResult { let stmt = conn.prepare("SELECT * FROM categories \ WHERE category = $1")?; let rows = stmt.query(&[&name])?; - rows.iter() - .next() - .chain_error(|| NotFound) - .map(|row| Model::from_row(&row)) + rows.iter().next() + .chain_error(|| NotFound) + .map(|row| Model::from_row(&row)) } - pub fn find_by_slug(conn: &GenericConnection, slug: &str) -> CargoResult { + pub fn find_by_slug(conn: &GenericConnection, slug: &str) + -> CargoResult { let stmt = conn.prepare("SELECT * FROM categories \ WHERE slug = LOWER($1)")?; let rows = stmt.query(&[&slug])?; - rows.iter() - .next() - .chain_error(|| NotFound) - .map(|row| Model::from_row(&row)) + rows.iter().next() + .chain_error(|| NotFound) + .map(|row| Model::from_row(&row)) } pub fn encodable(self) -> EncodableCategory { let Category { - crates_cnt, - category, - slug, - description, - created_at, - .. + crates_cnt, category, slug, description, created_at, .. } = self; EncodableCategory { id: slug.clone(), @@ -98,68 +93,59 @@ impl Category { pub fn update_crate<'a>(conn: &PgConnection, krate: &Crate, - slugs: &[&'a str]) - -> QueryResult> { + slugs: &[&'a str]) -> QueryResult> { use diesel::expression::dsl::any; conn.transaction(|| { let categories = categories::table .filter(categories::slug.eq(any(slugs))) .load::(conn)?; - let invalid_categories = slugs - .iter() - .cloned() + let invalid_categories = slugs.iter().cloned() .filter(|s| !categories.iter().any(|c| c.slug == *s)) .collect(); - let crate_categories = categories - .iter() - .map(|c| { - CrateCategory { - category_id: c.id, - crate_id: krate.id, - } - }) + let crate_categories = categories.iter() + .map(|c| CrateCategory { category_id: c.id, crate_id: krate.id }) .collect::>(); delete(CrateCategory::belonging_to(krate)).execute(conn)?; - insert(&crate_categories) - .into(crates_categories::table) - .execute(conn)?; + insert(&crate_categories).into(crates_categories::table).execute(conn)?; Ok(invalid_categories) }) } pub fn update_crate_old(conn: &GenericConnection, - krate: &Crate, - categories: &[String]) - -> CargoResult> { + krate: &Crate, + categories: &[String]) -> CargoResult> { let old_categories = krate.categories(conn)?; - let old_categories_ids: HashSet<_> = old_categories.iter().map(|cat| cat.id).collect(); + let old_categories_ids: HashSet<_> = old_categories.iter().map(|cat| { + cat.id + }).collect(); // If a new category specified is not in the database, filter // it out and don't add it. Return it to be able to warn about it. let mut invalid_categories = vec![]; - let new_categories: Vec = categories - .iter() - .flat_map(|c| match Category::find_by_slug(conn, c) { - Ok(cat) => Some(cat), - Err(_) => { - invalid_categories.push(c.to_string()); - None - } - }) - .collect(); - - let new_categories_ids: HashSet<_> = new_categories.iter().map(|cat| cat.id).collect(); + let new_categories: Vec = categories.iter().flat_map(|c| { + match Category::find_by_slug(conn, c) { + Ok(cat) => Some(cat), + Err(_) => { + invalid_categories.push(c.to_string()); + None + }, + } + }).collect(); + + let new_categories_ids: HashSet<_> = new_categories.iter().map(|cat| { + cat.id + }).collect(); let to_rm: Vec<_> = old_categories_ids - .difference(&new_categories_ids) - .cloned() - .collect(); + .difference(&new_categories_ids) + .cloned() + .collect(); let to_add: Vec<_> = new_categories_ids - .difference(&old_categories_ids) - .cloned() - .collect(); + .difference(&old_categories_ids) + .cloned() + .collect(); if !to_rm.is_empty() { conn.execute("DELETE FROM crates_categories \ @@ -169,10 +155,9 @@ impl Category { } if !to_add.is_empty() { - let insert: Vec<_> = to_add - .into_iter() - .map(|id| format!("({}, {})", krate.id, id)) - .collect(); + let insert: Vec<_> = to_add.into_iter().map(|id| { + format!("({}, {})", krate.id, id) + }).collect(); let insert = insert.join(", "); conn.execute(&format!("INSERT INTO crates_categories \ (crate_id, category_id) VALUES {}", @@ -198,8 +183,7 @@ impl Category { pub fn toplevel(conn: &PgConnection, sort: &str, limit: i64, - offset: i64) - -> QueryResult> { + offset: i64) -> QueryResult> { use diesel::select; use diesel::expression::dsl::*; @@ -219,15 +203,13 @@ impl Category { GROUP BY c.id {} LIMIT {} OFFSET {}", sort_sql, limit, offset - ))) - .load(conn) + ))).load(conn) } pub fn toplevel_old(conn: &GenericConnection, - sort: &str, - limit: i64, - offset: i64) - -> CargoResult> { + sort: &str, + limit: i64, + offset: i64) -> CargoResult> { let sort_sql = match sort { "crates" => "ORDER BY crates_cnt DESC", @@ -255,7 +237,8 @@ impl Category { Ok(categories) } - pub fn subcategories(&self, conn: &GenericConnection) -> CargoResult> { + pub fn subcategories(&self, conn: &GenericConnection) + -> CargoResult> { let stmt = conn.prepare("\ SELECT c.id, c.category, c.slug, c.description, c.created_at, \ COALESCE (( \ @@ -294,7 +277,8 @@ impl<'a> NewCategory<'a> { return Ok(c); } - categories.filter(slug.eq(self.slug)).first(conn) + categories.filter(slug.eq(self.slug)) + .first(conn) } } @@ -309,9 +293,7 @@ impl Model for Category { description: row.get("description"), } } - fn table_name(_: Option) -> &'static str { - "categories" - } + fn table_name(_: Option) -> &'static str { "categories" } } /// Handles the `GET /categories` route. @@ -328,19 +310,14 @@ pub fn index(req: &mut Request) -> CargoResult { let total = Category::count_toplevel(conn)?; #[derive(RustcEncodable)] - struct R { - categories: Vec, - meta: Meta, - } + struct R { categories: Vec, meta: Meta } #[derive(RustcEncodable)] - struct Meta { - total: i64, - } + struct Meta { total: i64 } Ok(req.json(&R { - categories: categories, - meta: Meta { total: total }, - })) + categories: categories, + meta: Meta { total: total }, + })) } /// Handles the `GET /categories/:category_id` route. @@ -348,10 +325,9 @@ pub fn show(req: &mut Request) -> CargoResult { let slug = &req.params()["category_id"]; let conn = req.tx()?; let cat = Category::find_by_slug(conn, slug)?; - let subcats = cat.subcategories(conn)? - .into_iter() - .map(|s| s.encodable()) - .collect(); + let subcats = cat.subcategories(conn)?.into_iter().map(|s| { + s.encodable() + }).collect(); let cat = cat.encodable(); let cat_with_subcats = EncodableCategoryWithSubcategories { id: cat.id, @@ -364,9 +340,7 @@ pub fn show(req: &mut Request) -> CargoResult { }; #[derive(RustcEncodable)] - struct R { - category: EncodableCategoryWithSubcategories, - } + struct R { category: EncodableCategoryWithSubcategories} Ok(req.json(&R { category: cat_with_subcats })) } @@ -378,25 +352,15 @@ pub fn slugs(req: &mut Request) -> CargoResult { let rows = stmt.query(&[])?; #[derive(RustcEncodable)] - struct Slug { - id: String, - slug: String, - } + struct Slug { id: String, slug: String } - let slugs: Vec = rows.iter() - .map(|r| { - let slug: String = r.get("slug"); - Slug { - id: slug.clone(), - slug: slug, - } - }) - .collect(); + let slugs: Vec = rows.iter().map(|r| { + let slug: String = r.get("slug"); + Slug { id: slug.clone(), slug: slug } + }).collect(); #[derive(RustcEncodable)] - struct R { - category_slugs: Vec, - } + struct R { category_slugs: Vec } Ok(req.json(&R { category_slugs: slugs })) } @@ -413,8 +377,7 @@ mod tests { .expect("TEST_DATABASE_URL must be set to run tests"); let conn = PgConnection::establish(&database_url).unwrap(); // These tests deadlock if run concurrently - conn.batch_execute("BEGIN; LOCK categories IN ACCESS EXCLUSIVE MODE") - .unwrap(); + conn.batch_execute("BEGIN; LOCK categories IN ACCESS EXCLUSIVE MODE").unwrap(); conn } @@ -423,14 +386,10 @@ mod tests { let conn = pg_connection(); conn.batch_execute("INSERT INTO categories (category, slug) VALUES ('Cat 2', 'cat2'), ('Cat 1', 'cat1'), ('Cat 1::sub', 'cat1::sub') - ") - .unwrap(); - - let categories = Category::toplevel(&conn, "", 10, 0) - .unwrap() - .into_iter() - .map(|c| c.category) - .collect::>(); + ").unwrap(); + + let categories = Category::toplevel(&conn, "", 10, 0).unwrap() + .into_iter().map(|c| c.category).collect::>(); let expected = vec!["Cat 1".to_string(), "Cat 2".to_string()]; assert_eq!(expected, categories); } @@ -440,14 +399,10 @@ mod tests { let conn = pg_connection(); conn.batch_execute("INSERT INTO categories (category, slug, crates_cnt) VALUES ('Cat 1', 'cat1', 0), ('Cat 2', 'cat2', 2), ('Cat 3', 'cat3', 1) - ") - .unwrap(); - - let categories = Category::toplevel(&conn, "crates", 10, 0) - .unwrap() - .into_iter() - .map(|c| c.category) - .collect::>(); + ").unwrap(); + + let categories = Category::toplevel(&conn, "crates", 10, 0).unwrap() + .into_iter().map(|c| c.category).collect::>(); let expected = vec!["Cat 2".to_string(), "Cat 3".to_string(), "Cat 1".to_string()]; assert_eq!(expected, categories); } @@ -457,22 +412,15 @@ mod tests { let conn = pg_connection(); conn.batch_execute("INSERT INTO categories (category, slug) VALUES ('Cat 1', 'cat1'), ('Cat 2', 'cat2') - ") - .unwrap(); - - let categories = Category::toplevel(&conn, "", 1, 0) - .unwrap() - .into_iter() - .map(|c| c.category) - .collect::>(); + ").unwrap(); + + let categories = Category::toplevel(&conn, "", 1, 0).unwrap() + .into_iter().map(|c| c.category).collect::>(); let expected = vec!["Cat 1".to_string()]; assert_eq!(expected, categories); - let categories = Category::toplevel(&conn, "", 1, 1) - .unwrap() - .into_iter() - .map(|c| c.category) - .collect::>(); + let categories = Category::toplevel(&conn, "", 1, 1).unwrap() + .into_iter().map(|c| c.category).collect::>(); let expected = vec!["Cat 2".to_string()]; assert_eq!(expected, categories); } @@ -484,14 +432,10 @@ mod tests { ('Cat 1', 'cat1', 1), ('Cat 1::sub', 'cat1::sub', 2), ('Cat 2', 'cat2', 3), ('Cat 2::Sub 1', 'cat2::sub1', 4), ('Cat 2::Sub 2', 'cat2::sub2', 5), ('Cat 3', 'cat3', 6) - ") - .unwrap(); - - let categories = Category::toplevel(&conn, "crates", 10, 0) - .unwrap() - .into_iter() - .map(|c| (c.category, c.crates_cnt)) - .collect::>(); + ").unwrap(); + + let categories = Category::toplevel(&conn, "crates", 10, 0).unwrap() + .into_iter().map(|c| (c.category, c.crates_cnt)).collect::>(); let expected = vec![ ("Cat 2".to_string(), 12), ("Cat 3".to_string(), 6), @@ -507,25 +451,18 @@ mod tests { ('Cat 1', 'cat1', 1), ('Cat 1::sub', 'cat1::sub', 2), ('Cat 2', 'cat2', 3), ('Cat 2::Sub 1', 'cat2::sub1', 4), ('Cat 2::Sub 2', 'cat2::sub2', 5), ('Cat 3', 'cat3', 6) - ") - .unwrap(); - - let categories = Category::toplevel(&conn, "crates", 2, 0) - .unwrap() - .into_iter() - .map(|c| (c.category, c.crates_cnt)) - .collect::>(); + ").unwrap(); + + let categories = Category::toplevel(&conn, "crates", 2, 0).unwrap() + .into_iter().map(|c| (c.category, c.crates_cnt)).collect::>(); let expected = vec![ ("Cat 2".to_string(), 12), ("Cat 3".to_string(), 6), ]; assert_eq!(expected, categories); - let categories = Category::toplevel(&conn, "crates", 2, 1) - .unwrap() - .into_iter() - .map(|c| (c.category, c.crates_cnt)) - .collect::>(); + let categories = Category::toplevel(&conn, "crates", 2, 1).unwrap() + .into_iter().map(|c| (c.category, c.crates_cnt)).collect::>(); let expected = vec![ ("Cat 3".to_string(), 6), ("Cat 1".to_string(), 3), diff --git a/src/db.rs b/src/db.rs index a416c73ebf8..68a39c5a9c4 100644 --- a/src/db.rs +++ b/src/db.rs @@ -75,7 +75,8 @@ pub fn tls_handshake() -> Box { } let mut builder = SslConnectorBuilder::new(SslMethod::tls()).unwrap(); - builder.builder_mut().set_verify(SSL_VERIFY_NONE); + builder.builder_mut() + .set_verify(SSL_VERIFY_NONE); Box::new(MyHandshake(builder.build())) } @@ -102,9 +103,7 @@ pub fn pool(url: &str, config: r2d2::Config) - -> DieselPool { +pub fn diesel_pool(url: &str, config: r2d2::Config) -> DieselPool { let mut url = Url::parse(url).expect("Invalid database URL"); if env::var("HEROKU").is_ok() && !url.query_pairs().any(|(k, _)| k == "sslmode") { url.query_pairs_mut().append_pair("sslmode", "require"); @@ -144,17 +143,11 @@ impl Transaction { } } - pub fn conn - (&self) - -> CargoResult<&r2d2::PooledConnection> { + pub fn conn(&self) -> CargoResult<&r2d2::PooledConnection> { if !self.slot.filled() { - let conn = - self.app - .database - .get() - .map_err(|e| { - internal(&format_args!("failed to get a database connection: {}", e)) - })?; + let conn = self.app.database.get().map_err(|e| { + internal(&format_args!("failed to get a database connection: {}", e)) + })?; self.slot.fill(Box::new(conn)); } Ok(&**self.slot.borrow().unwrap()) @@ -190,26 +183,23 @@ impl Transaction { } impl Middleware for TransactionMiddleware { - fn before(&self, req: &mut Request) -> Result<(), Box> { + fn before(&self, req: &mut Request) -> Result<(), Box> { let app = req.app().clone(); req.mut_extensions().insert(Transaction::new(app)); Ok(()) } - fn after(&self, - req: &mut Request, - res: Result>) - -> Result> { - let tx = req.mut_extensions() - .pop::() - .expect("Transaction not present in request"); + fn after(&self, req: &mut Request, res: Result>) + -> Result> { + let tx = req.mut_extensions().pop::() + .expect("Transaction not present in request"); if let Some(transaction) = tx.tx.into_inner() { if res.is_ok() && tx.commit.get() == Some(true) { transaction.set_commit(); } - transaction - .finish() - .map_err(|e| Box::new(e) as Box)?; + transaction.finish().map_err(|e| { + Box::new(e) as Box + })?; } res } @@ -235,26 +225,24 @@ pub trait RequestTransaction { impl RequestTransaction for T { fn db_conn(&self) -> CargoResult { - self.app().diesel_database.get().map_err(Into::into) + self.app().diesel_database.get() + .map_err(Into::into) } fn tx(&self) -> CargoResult<&GenericConnection> { - self.extensions() - .find::() + self.extensions().find::() .expect("Transaction not present in request") .tx() } fn rollback(&self) { - self.extensions() - .find::() + self.extensions().find::() .expect("Transaction not present in request") .rollback() } fn commit(&self) { - self.extensions() - .find::() + self.extensions().find::() .expect("Transaction not present in request") .commit() } diff --git a/src/dependency.rs b/src/dependency.rs index 59f06a927af..08e3f3cc06f 100644 --- a/src/dependency.rs +++ b/src/dependency.rs @@ -72,15 +72,10 @@ pub struct NewDependency<'a> { impl Dependency { // FIXME: Encapsulate this in a `NewDependency` struct #[cfg_attr(feature = "clippy", allow(too_many_arguments))] - pub fn insert(conn: &GenericConnection, - version_id: i32, - crate_id: i32, - req: &semver::VersionReq, - kind: Kind, - optional: bool, - default_features: bool, - features: &[String], - target: &Option) + pub fn insert(conn: &GenericConnection, version_id: i32, crate_id: i32, + req: &semver::VersionReq, kind: Kind, + optional: bool, default_features: bool, + features: &[String], target: &Option) -> CargoResult { let req = req.to_string(); let stmt = conn.prepare("INSERT INTO dependencies @@ -88,14 +83,9 @@ impl Dependency { default_features, features, target, kind) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *")?; - let rows = stmt.query(&[&version_id, - &crate_id, - &req, - &optional, - &default_features, - &features, - target, - &(kind as i32)])?; + let rows = stmt.query(&[&version_id, &crate_id, &req, + &optional, &default_features, + &features, target, &(kind as i32)])?; Ok(Model::from_row(&rows.iter().next().unwrap())) } @@ -118,65 +108,65 @@ impl Dependency { impl ReverseDependency { pub fn encodable(self) -> EncodableDependency { - self.dependency - .encodable(&self.crate_name, Some(self.crate_downloads)) + self.dependency.encodable(&self.crate_name, Some(self.crate_downloads)) } } -pub fn add_dependencies(conn: &PgConnection, - deps: &[::upload::CrateDependency], - version_id: i32) - -> CargoResult> { +pub fn add_dependencies( + conn: &PgConnection, + deps: &[::upload::CrateDependency], + version_id: i32, +) -> CargoResult> { use diesel::insert; - let git_and_new_dependencies = deps.iter() - .map(|dep| { - let krate = - Crate::by_name(&dep.name) - .first::(&*conn) - .map_err(|_| human(&format_args!("no known crate named `{}`", &*dep.name)))?; - if dep.version_req == semver::VersionReq::parse("*").unwrap() { - return Err(human("wildcard (`*`) dependency constraints are not allowed \ + let git_and_new_dependencies = deps.iter().map(|dep| { + let krate = Crate::by_name(&dep.name).first::(&*conn) + .map_err(|_| { + human(&format_args!("no known crate named `{}`", &*dep.name)) + })?; + if dep.version_req == semver::VersionReq::parse("*").unwrap() { + return Err(human("wildcard (`*`) dependency constraints are not allowed \ on crates.io. See http://doc.crates.io/faq.html#can-\ libraries-use--as-a-version-for-their-dependencies for more \ information")); + } + let features: Vec<_> = dep.features.iter().map(|s| &**s).collect(); + + Ok(( + git::Dependency { + name: dep.name.to_string(), + req: dep.version_req.to_string(), + features: features.iter().map(|s| s.to_string()).collect(), + optional: dep.optional, + default_features: dep.default_features, + target: dep.target.clone(), + kind: dep.kind.or(Some(Kind::Normal)), + }, + NewDependency { + version_id: version_id, + crate_id: krate.id, + req: dep.version_req.to_string(), + kind: dep.kind.unwrap_or(Kind::Normal) as i32, + optional: dep.optional, + default_features: dep.default_features, + features: features, + target: dep.target.as_ref().map(|s| &**s), } - let features: Vec<_> = dep.features.iter().map(|s| &**s).collect(); - - Ok((git::Dependency { - name: dep.name.to_string(), - req: dep.version_req.to_string(), - features: features.iter().map(|s| s.to_string()).collect(), - optional: dep.optional, - default_features: dep.default_features, - target: dep.target.clone(), - kind: dep.kind.or(Some(Kind::Normal)), - }, - NewDependency { - version_id: version_id, - crate_id: krate.id, - req: dep.version_req.to_string(), - kind: dep.kind.unwrap_or(Kind::Normal) as i32, - optional: dep.optional, - default_features: dep.default_features, - features: features, - target: dep.target.as_ref().map(|s| &**s), - })) - }) - .collect::, _>>()?; + )) + }).collect::, _>>()?; let (git_deps, new_dependencies): (Vec<_>, Vec<_>) = git_and_new_dependencies.into_iter().unzip(); - insert(&new_dependencies) - .into(dependencies::table) + insert(&new_dependencies).into(dependencies::table) .execute(conn)?; Ok(git_deps) } impl Queryable for Dependency { - type Row = (i32, i32, i32, String, bool, bool, Vec, Option, i32); + type Row = (i32, i32, i32, String, bool, bool, Vec, Option, + i32); fn build(row: Self::Row) -> Self { Dependency { @@ -193,7 +183,7 @@ impl Queryable for Dependency { 1 => Kind::Build, 2 => Kind::Dev, n => panic!("unknown kind: {}", n), - }, + } } } } @@ -215,13 +205,11 @@ impl Model for Dependency { 1 => Kind::Build, 2 => Kind::Dev, n => panic!("unknown kind: {}", n), - }, + } } } - fn table_name(_: Option) -> &'static str { - "dependencies" - } + fn table_name(_: Option) -> &'static str { "dependencies" } } impl Model for ReverseDependency { @@ -233,7 +221,5 @@ impl Model for ReverseDependency { } } - fn table_name(_: Option) -> &'static str { - panic!("no table") - } + fn table_name(_: Option) -> &'static str { panic!("no table") } } diff --git a/src/dist.rs b/src/dist.rs index 501fb51eff1..3ba232629bf 100644 --- a/src/dist.rs +++ b/src/dist.rs @@ -11,7 +11,7 @@ pub struct Middleware { dist: Static, } -impl Default for Middleware { +impl Default for Middleware { fn default() -> Middleware { Middleware { handler: None, @@ -27,7 +27,7 @@ impl AroundMiddleware for Middleware { } impl Handler for Middleware { - fn call(&self, req: &mut Request) -> Result> { + fn call(&self, req: &mut Request) -> Result> { // First, attempt to serve a static file. If we're missing a static // file, then keep going. match self.dist.call(req) { @@ -37,17 +37,15 @@ impl Handler for Middleware { // Second, if we're requesting html, then we've only got one page so // serve up that page. Otherwise proxy on to the rest of the app. - let wants_html = req.headers() - .find("Accept") - .map(|accept| accept.iter().any(|s| s.contains("html"))) - .unwrap_or(false); + let wants_html = req.headers().find("Accept").map(|accept| { + accept.iter().any(|s| s.contains("html")) + }).unwrap_or(false); if wants_html { - self.dist - .call(&mut RequestProxy { - other: req, - path: Some("/index.html"), - method: None, - }) + self.dist.call(&mut RequestProxy { + other: req, + path: Some("/index.html"), + method: None, + }) } else { self.handler.as_ref().unwrap().call(req) } diff --git a/src/download.rs b/src/download.rs index cc5e6a4d952..0df4d0c8cee 100644 --- a/src/download.rs +++ b/src/download.rs @@ -21,8 +21,7 @@ pub struct VersionDownload { #[derive(Insertable)] #[table_name="version_downloads"] -struct NewVersionDownload(#[column_name(version_id)] - i32); +struct NewVersionDownload(#[column_name(version_id)] i32); #[derive(RustcEncodable, RustcDecodable)] pub struct EncodableVersionDownload { @@ -41,12 +40,11 @@ impl VersionDownload { // nothing else. We have lots of other counters, but they're // all updated later on via the update-downloads script. let new_download = NewVersionDownload(version); - let downloads_row = - new_download.on_conflict((version_id, date), - do_update().set(downloads.eq(downloads + 1))); - diesel::insert(&downloads_row) - .into(version_downloads) - .execute(conn)?; + let downloads_row = new_download + .on_conflict((version_id, date), do_update().set( + downloads.eq(downloads + 1) + )); + diesel::insert(&downloads_row).into(version_downloads).execute(conn)?; Ok(()) } @@ -72,7 +70,5 @@ impl Model for VersionDownload { } } - fn table_name(_: Option) -> &'static str { - "version_downloads" - } + fn table_name(_: Option) -> &'static str { "version_downloads" } } diff --git a/src/git.rs b/src/git.rs index dd9c17cc157..ac97a3d1ab0 100644 --- a/src/git.rs +++ b/src/git.rs @@ -34,14 +34,14 @@ pub struct Dependency { } fn index_file(base: &Path, name: &str) -> PathBuf { - let name = name.chars() - .flat_map(|c| c.to_lowercase()) - .collect::(); + let name = name.chars().flat_map(|c| c.to_lowercase()).collect::(); match name.len() { 1 => base.join("1").join(&name), 2 => base.join("2").join(&name), 3 => base.join("3").join(&name[..1]).join(&name), - _ => base.join(&name[0..2]).join(&name[2..4]).join(&name), + _ => base.join(&name[0..2]) + .join(&name[2..4]) + .join(&name), } } @@ -56,8 +56,7 @@ pub fn add_crate(app: &App, krate: &Crate) -> CargoResult<()> { fs::create_dir_all(dst.parent().unwrap())?; let mut prev = String::new(); if fs::metadata(&dst).is_ok() { - File::open(&dst) - .and_then(|mut f| f.read_to_string(&mut prev))?; + File::open(&dst).and_then(|mut f| f.read_to_string(&mut prev))?; } let s = json::encode(krate).unwrap(); let new = prev + &s; @@ -65,31 +64,31 @@ pub fn add_crate(app: &App, krate: &Crate) -> CargoResult<()> { f.write_all(new.as_bytes())?; f.write_all(b"\n")?; - Ok((format!("Updating crate `{}#{}`", krate.name, krate.vers), dst.clone())) + Ok((format!("Updating crate `{}#{}`", krate.name, krate.vers), + dst.clone())) }) } -pub fn yank(app: &App, krate: &str, version: &semver::Version, yanked: bool) -> CargoResult<()> { +pub fn yank(app: &App, krate: &str, version: &semver::Version, + yanked: bool) -> CargoResult<()> { let repo = app.git_repo.lock().unwrap(); let repo_path = repo.workdir().unwrap(); let dst = index_file(repo_path, krate); commit_and_push(&repo, || { let mut prev = String::new(); - File::open(&dst) - .and_then(|mut f| f.read_to_string(&mut prev))?; - let new = prev.lines() - .map(|line| { - let mut git_crate = - json::decode::(line) - .map_err(|_| internal(&format_args!("couldn't decode: `{}`", line)))?; - if git_crate.name != krate || git_crate.vers != version.to_string() { - return Ok(line.to_string()); - } - git_crate.yanked = Some(yanked); - Ok(json::encode(&git_crate).unwrap()) - }) - .collect::>>(); + File::open(&dst).and_then(|mut f| f.read_to_string(&mut prev))?; + let new = prev.lines().map(|line| { + let mut git_crate = json::decode::(line).map_err(|_| { + internal(&format_args!("couldn't decode: `{}`", line)) + })?; + if git_crate.name != krate || + git_crate.vers != version.to_string() { + return Ok(line.to_string()) + } + git_crate.yanked = Some(yanked); + Ok(json::encode(&git_crate).unwrap()) + }).collect::>>(); let new = new?.join("\n"); let mut f = File::create(&dst)?; f.write_all(new.as_bytes())?; @@ -117,9 +116,8 @@ fn commit_and_push(repo: &git2::Repository, mut f: F) -> CargoResult<()> // git add $file let mut index = repo.index()?; let mut repo_path = repo_path.iter(); - let dst = dst.iter() - .skip_while(|s| Some(*s) == repo_path.next()) - .collect::(); + let dst = dst.iter().skip_while(|s| Some(*s) == repo_path.next()) + .collect::(); index.add_path(&dst)?; index.write()?; let tree_id = index.write_tree()?; @@ -154,11 +152,9 @@ fn commit_and_push(repo: &git2::Repository, mut f: F) -> CargoResult<()> let mut callbacks = git2::RemoteCallbacks::new(); callbacks.credentials(credentials); - origin - .update_tips(Some(&mut callbacks), - true, - git2::AutotagOption::Unspecified, - None)?; + origin.update_tips(Some(&mut callbacks), true, + git2::AutotagOption::Unspecified, + None)?; // Ok, we need to update, so fetch and reset --hard origin.fetch(&["refs/heads/*:refs/heads/*"], None, None)?; @@ -170,12 +166,13 @@ fn commit_and_push(repo: &git2::Repository, mut f: F) -> CargoResult<()> Err(internal("Too many rebase failures")) } -pub fn credentials(_user: &str, - _user_from_url: Option<&str>, +pub fn credentials(_user: &str, _user_from_url: Option<&str>, _cred: git2::CredentialType) -> Result { match (env::var("GIT_HTTP_USER"), env::var("GIT_HTTP_PWD")) { - (Ok(u), Ok(p)) => git2::Cred::userpass_plaintext(&u, &p), - _ => Err(git2::Error::from_str("no authentication set")), + (Ok(u), Ok(p)) => { + git2::Cred::userpass_plaintext(&u, &p) + } + _ => Err(git2::Error::from_str("no authentication set")) } } diff --git a/src/http.rs b/src/http.rs index e45572b87cc..a62cd3ad1b7 100644 --- a/src/http.rs +++ b/src/http.rs @@ -10,18 +10,15 @@ use std::str; /// Does all the nonsense for sending a GET to Github. Doesn't handle parsing /// because custom error-code handling may be desirable. Use /// `parse_github_response` to handle the "common" processing of responses. -pub fn github(app: &App, url: &str, auth: &Token) -> Result<(Easy, Vec), curl::Error> { +pub fn github(app: &App, url: &str, auth: &Token) + -> Result<(Easy, Vec), curl::Error> { let url = format!("{}://api.github.com{}", app.config.api_protocol, url); info!("GITHUB HTTP: {}", url); let mut headers = List::new(); - headers - .append("Accept: application/vnd.github.v3+json") - .unwrap(); + headers.append("Accept: application/vnd.github.v3+json").unwrap(); headers.append("User-Agent: hello!").unwrap(); - headers - .append(&format!("Authorization: token {}", auth.access_token)) - .unwrap(); + headers.append(&format!("Authorization: token {}", auth.access_token)).unwrap(); let mut handle = app.handle(); handle.url(&url).unwrap(); @@ -31,19 +28,18 @@ pub fn github(app: &App, url: &str, auth: &Token) -> Result<(Easy, Vec), cur let mut data = Vec::new(); { let mut transfer = handle.transfer(); - transfer - .write_function(|buf| { - data.extend_from_slice(buf); - Ok(buf.len()) - }) - .unwrap(); + transfer.write_function(|buf| { + data.extend_from_slice(buf); + Ok(buf.len()) + }).unwrap(); transfer.perform()?; } Ok((handle, data)) } /// Checks for normal responses -pub fn parse_github_response(mut resp: Easy, data: &[u8]) -> CargoResult { +pub fn parse_github_response(mut resp: Easy, data: &[u8]) + -> CargoResult { match resp.response_code().unwrap() { 200 => {} // Ok! 403 => { @@ -62,11 +58,13 @@ pub fn parse_github_response(mut resp: Easy, data: &[u8]) -> Cargo } } - let json = str::from_utf8(data) - .ok() - .chain_error(|| internal("github didn't send a utf8-response"))?; + let json = str::from_utf8(data).ok().chain_error(|| { + internal("github didn't send a utf8-response") + })?; - json::decode(json).chain_error(|| internal("github didn't send a valid json response")) + json::decode(json).chain_error(|| { + internal("github didn't send a valid json response") + }) } /// Gets a token with the given string as the access token, but all diff --git a/src/keyword.rs b/src/keyword.rs index c4c8a377d9f..6c53d5877ad 100644 --- a/src/keyword.rs +++ b/src/keyword.rs @@ -40,7 +40,8 @@ pub struct EncodableKeyword { } impl Keyword { - pub fn find_by_keyword(conn: &PgConnection, name: &str) -> QueryResult { + pub fn find_by_keyword(conn: &PgConnection, name: &str) + -> QueryResult { keywords::table .filter(keywords::keyword.eq(::lower(name))) .first(&*conn) @@ -56,10 +57,11 @@ impl Keyword { keyword: &'a str, } - let lowercase_names: Vec<_> = names.iter().map(|s| s.to_lowercase()).collect(); + let lowercase_names: Vec<_> = names.iter() + .map(|s| s.to_lowercase()) + .collect(); - let new_keywords: Vec<_> = lowercase_names - .iter() + let new_keywords: Vec<_> = lowercase_names.iter() .map(|s| NewKeyword { keyword: s }) .collect(); @@ -75,22 +77,14 @@ impl Keyword { } pub fn valid_name(name: &str) -> bool { - if name.is_empty() { - return false; - } + if name.is_empty() { return false } name.chars().next().unwrap().is_alphanumeric() && - name.chars() - .all(|c| c.is_alphanumeric() || c == '_' || c == '-') && - name.chars().all(|c| c.is_ascii()) + name.chars().all(|c| c.is_alphanumeric() || c == '_' || c == '-') && + name.chars().all(|c| c.is_ascii()) } pub fn encodable(self) -> EncodableKeyword { - let Keyword { - crates_cnt, - keyword, - created_at, - .. - } = self; + let Keyword { crates_cnt, keyword, created_at, .. } = self; EncodableKeyword { id: keyword.clone(), created_at: ::encode_time(created_at), @@ -99,22 +93,17 @@ impl Keyword { } } - pub fn update_crate(conn: &PgConnection, krate: &Crate, keywords: &[&str]) -> QueryResult<()> { + pub fn update_crate(conn: &PgConnection, + krate: &Crate, + keywords: &[&str]) -> QueryResult<()> { conn.transaction(|| { let keywords = Keyword::find_or_create_all(conn, keywords)?; diesel::delete(CrateKeyword::belonging_to(krate)) .execute(conn)?; - let crate_keywords = keywords - .into_iter() - .map(|kw| { - CrateKeyword { - crate_id: krate.id, - keyword_id: kw.id, - } - }) - .collect::>(); - diesel::insert(&crate_keywords) - .into(crates_keywords::table) + let crate_keywords = keywords.into_iter().map(|kw| { + CrateKeyword { crate_id: krate.id, keyword_id: kw.id } + }).collect::>(); + diesel::insert(&crate_keywords).into(crates_keywords::table) .execute(conn)?; Ok(()) }) @@ -130,9 +119,7 @@ impl Model for Keyword { keyword: row.get("keyword"), } } - fn table_name(_: Option) -> &'static str { - "keywords" - } + fn table_name(_: Option) -> &'static str { "keywords" } } /// Handles the `GET /keywords` route. @@ -161,23 +148,17 @@ pub fn index(req: &mut Request) -> CargoResult { let data = query.load::<(Keyword, i64)>(&*conn)?; let total = data.get(0).map(|&(_, t)| t).unwrap_or(0); let kws = data.into_iter() - .map(|(k, _)| k.encodable()) - .collect::>(); + .map(|(k, _)| k.encodable()).collect::>(); #[derive(RustcEncodable)] - struct R { - keywords: Vec, - meta: Meta, - } + struct R { keywords: Vec, meta: Meta } #[derive(RustcEncodable)] - struct Meta { - total: i64, - } + struct Meta { total: i64 } Ok(req.json(&R { - keywords: kws, - meta: Meta { total: total }, - })) + keywords: kws, + meta: Meta { total: total }, + })) } /// Handles the `GET /keywords/:keyword_id` route. @@ -188,8 +169,6 @@ pub fn show(req: &mut Request) -> CargoResult { let kw = Keyword::find_by_keyword(&conn, name)?; #[derive(RustcEncodable)] - struct R { - keyword: EncodableKeyword, - } + struct R { keyword: EncodableKeyword } Ok(req.json(&R { keyword: kw.encodable() })) } diff --git a/src/krate.rs b/src/krate.rs index 2c5e49bf6e2..9323825567c 100644 --- a/src/krate.rs +++ b/src/krate.rs @@ -56,31 +56,16 @@ pub struct Crate { /// We literally never want to select `textsearchable_index_col` /// so we provide this type and constant to pass to `.select` -type AllColumns = (crates::id, - crates::name, - crates::updated_at, - crates::created_at, - crates::downloads, - crates::description, - crates::homepage, - crates::documentation, - crates::readme, - crates::license, - crates::repository, - crates::max_upload_size); - -pub const ALL_COLUMNS: AllColumns = (crates::id, - crates::name, - crates::updated_at, - crates::created_at, - crates::downloads, - crates::description, - crates::homepage, - crates::documentation, - crates::readme, - crates::license, - crates::repository, - crates::max_upload_size); +type AllColumns = (crates::id, crates::name, crates::updated_at, + crates::created_at, crates::downloads, crates::description, + crates::homepage, crates::documentation, crates::readme, crates::license, + crates::repository, crates::max_upload_size); + +pub const ALL_COLUMNS: AllColumns = (crates::id, crates::name, + crates::updated_at, crates::created_at, crates::downloads, + crates::description, crates::homepage, crates::documentation, + crates::readme, crates::license, crates::repository, + crates::max_upload_size); pub const MAX_NAME_LENGTH: usize = 64; @@ -130,11 +115,12 @@ pub struct NewCrate<'a> { } impl<'a> NewCrate<'a> { - pub fn create_or_update(mut self, - conn: &PgConnection, - license_file: Option<&str>, - uploader: i32) - -> CargoResult { + pub fn create_or_update( + mut self, + conn: &PgConnection, + license_file: Option<&str>, + uploader: i32, + ) -> CargoResult { use diesel::update; self.validate(license_file)?; @@ -144,14 +130,13 @@ impl<'a> NewCrate<'a> { // To avoid race conditions, we try to insert // first so we know whether to add an owner if let Some(krate) = self.save_new_crate(conn, uploader)? { - return Ok(krate); + return Ok(krate) } - let target = - crates::table - .filter(canon_crate_name(crates::name).eq(canon_crate_name(self.name))); - update(target) - .set(&self) + let target = crates::table.filter( + canon_crate_name(crates::name) + .eq(canon_crate_name(self.name))); + update(target).set(&self) .returning(ALL_COLUMNS) .get_result(conn) .map_err(Into::into) @@ -162,21 +147,19 @@ impl<'a> NewCrate<'a> { fn validate_url(url: Option<&str>, field: &str) -> CargoResult<()> { let url = match url { Some(s) => s, - None => return Ok(()), + None => return Ok(()) }; let url = Url::parse(url).map_err(|_| { human(&format_args!("`{}` is not a valid url: `{}`", field, url)) })?; match &url.scheme()[..] { "http" | "https" => {} - s => { - return Err(human(&format_args!("`{}` has an invalid url \ + s => return Err(human(&format_args!("`{}` has an invalid url \ scheme: `{}`", field, s))) - } } if url.cannot_be_a_base() { return Err(human(&format_args!("`{}` must have relative scheme \ - data: {}", field, url))); + data: {}", field, url))) } Ok(()) } @@ -191,12 +174,10 @@ impl<'a> NewCrate<'a> { fn validate_license(&mut self, license_file: Option<&str>) -> CargoResult<()> { if let Some(license) = self.license { for part in license.split('/') { - license_exprs::validate_license_expr(part) - .map_err(|e| { - human(&format_args!("{}; see http://opensource.org/licenses \ + license_exprs::validate_license_expr(part) + .map_err(|e| human(&format_args!("{}; see http://opensource.org/licenses \ for options, and http://spdx.org/licenses/ \ - for their identifiers", e)) - })?; + for their identifiers", e)))?; } } else if license_file.is_some() { // If no license is given, but a license file is given, flag this @@ -212,10 +193,9 @@ impl<'a> NewCrate<'a> { use diesel::select; use diesel::expression::dsl::exists; - let reserved_name = - select(exists(reserved_crate_names - .filter(canon_crate_name(name).eq(canon_crate_name(self.name))))) - .get_result::(conn)?; + let reserved_name = select(exists(reserved_crate_names + .filter(canon_crate_name(name).eq(canon_crate_name(self.name))) + )).get_result::(conn)?; if reserved_name { Err(human("cannot upload a crate with a reserved name")) } else { @@ -228,8 +208,7 @@ impl<'a> NewCrate<'a> { use diesel::insert; conn.transaction(|| { - let maybe_inserted = insert(&self.on_conflict_do_nothing()) - .into(crates) + let maybe_inserted = insert(&self.on_conflict_do_nothing()).into(crates) .returning(ALL_COLUMNS) .get_result::(conn) .optional()?; @@ -241,7 +220,8 @@ impl<'a> NewCrate<'a> { created_by: user_id, owner_kind: OwnerKind::User as i32, }; - insert(&owner).into(crate_owners::table).execute(conn)?; + insert(&owner).into(crate_owners::table) + .execute(conn)?; } Ok(maybe_inserted) @@ -252,15 +232,18 @@ impl<'a> NewCrate<'a> { impl Crate { pub fn by_name(name: &str) -> CrateQuery { Crate::all() - .filter(canon_crate_name(crates::name).eq(canon_crate_name(name))) - .into_boxed() + .filter( + canon_crate_name(crates::name).eq( + canon_crate_name(name)) + ).into_boxed() } pub fn all() -> Select { crates::table.select(ALL_COLUMNS) } - pub fn find_by_name(conn: &GenericConnection, name: &str) -> CargoResult { + pub fn find_by_name(conn: &GenericConnection, + name: &str) -> CargoResult { let stmt = conn.prepare("SELECT * FROM crates \ WHERE canon_crate_name(name) = canon_crate_name($1) LIMIT 1")?; @@ -321,13 +304,10 @@ impl Crate { WHERE canon_crate_name(name) = canon_crate_name($7) RETURNING *")?; - let rows = stmt.query(&[&documentation, - &homepage, - &description, - &readme, - &license, - &repository, - &name])?; + let rows = stmt.query(&[&documentation, &homepage, + &description, &readme, + &license, &repository, + &name])?; if let Some(row) = rows.iter().next() { return Ok(Model::from_row(&row)); } @@ -337,7 +317,7 @@ impl Crate { canon_crate_name($1)")?; let rows = stmt.query(&[&name])?; if !rows.is_empty() { - return Err(human("cannot upload a crate with a reserved name")); + return Err(human("cannot upload a crate with a reserved name")) } let stmt = conn.prepare("INSERT INTO crates @@ -346,17 +326,12 @@ impl Crate { repository, license, max_upload_size) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *")?; - let rows = stmt.query(&[&name, - &description, - &homepage, - &documentation, - &readme, - &repository, - &license, - &max_upload_size])?; - let ret: Crate = Model::from_row(&rows.iter() - .next() - .chain_error(|| internal("no crate returned"))?); + let rows = stmt.query(&[&name, &description, &homepage, + &documentation, &readme, + &repository, &license, &max_upload_size])?; + let ret: Crate = Model::from_row(&rows.iter().next().chain_error(|| { + internal("no crate returned") + })?); conn.execute("INSERT INTO crate_owners (crate_id, owner_id, created_by, owner_kind) @@ -367,54 +342,47 @@ impl Crate { fn validate_url(url: Option<&str>, field: &str) -> CargoResult<()> { let url = match url { Some(s) => s, - None => return Ok(()), + None => return Ok(()) }; let url = Url::parse(url).map_err(|_| { human(&format_args!("`{}` is not a valid url: `{}`", field, url)) })?; match &url.scheme()[..] { "http" | "https" => {} - s => { - return Err(human(&format_args!("`{}` has an invalid url \ + s => return Err(human(&format_args!("`{}` has an invalid url \ scheme: `{}`", field, s))) - } } if url.cannot_be_a_base() { return Err(human(&format_args!("`{}` must have relative scheme \ - data: {}", field, url))); + data: {}", field, url))) } Ok(()) } fn validate_license(license: Option<&str>) -> CargoResult<()> { - license - .iter() - .flat_map(|s| s.split('/')) - .map(license_exprs::validate_license_expr) - .collect::, _>>() - .map(|_| ()) - .map_err(|e| { - human(&format_args!("{}; see http://opensource.org/licenses \ + license.iter().flat_map(|s| s.split('/')) + .map(license_exprs::validate_license_expr) + .collect::, _>>() + .map(|_| ()) + .map_err(|e| human(&format_args!("{}; see http://opensource.org/licenses \ for options, and http://spdx.org/licenses/ \ - for their identifiers", e)) - }) + for their identifiers", e))) } } pub fn valid_name(name: &str) -> bool { - let under_max_length = name.chars().take(MAX_NAME_LENGTH + 1).count() <= MAX_NAME_LENGTH; + let under_max_length = name.chars() + .take(MAX_NAME_LENGTH + 1) + .count() <= MAX_NAME_LENGTH; Crate::valid_ident(name) && under_max_length } fn valid_ident(name: &str) -> bool { - if name.is_empty() { - return false; - } + if name.is_empty() { return false } name.chars().next().unwrap().is_alphabetic() && - name.chars() - .all(|c| c.is_alphanumeric() || c == '_' || c == '-') && - name.chars().all(|c| c.is_ascii()) + name.chars().all(|c| c.is_alphanumeric() || c == '_' || c == '-') && + name.chars().all(|c| c.is_ascii()) } pub fn valid_feature_name(name: &str) -> bool { @@ -433,9 +401,7 @@ impl Crate { pub fn minimal_encodable(self, max_version: semver::Version, - badges: Option>, - exact_match: bool) - -> EncodableCrate { + badges: Option>, exact_match: bool) -> EncodableCrate { self.encodable(max_version, None, None, None, badges, exact_match) } @@ -448,16 +414,8 @@ impl Crate { exact_match: bool) -> EncodableCrate { let Crate { - name, - created_at, - updated_at, - downloads, - description, - homepage, - documentation, - license, - repository, - .. + name, created_at, updated_at, downloads, description, + homepage, documentation, license, repository, .. } = self; let versions_link = match versions { Some(..) => None, @@ -465,7 +423,9 @@ impl Crate { }; let keyword_ids = keywords.map(|kws| kws.iter().map(|kw| kw.keyword.clone()).collect()); let category_ids = categories.map(|cats| cats.iter().map(|cat| cat.slug.clone()).collect()); - let badges = badges.map(|bs| bs.into_iter().map(|b| b.encodable()).collect()); + let badges = badges.map(|bs| { + bs.into_iter().map(|b| b.encodable()).collect() + }); EncodableCrate { id: name.clone(), name: name.clone(), @@ -487,7 +447,7 @@ impl Crate { version_downloads: format!("/api/v1/crates/{}/downloads", name), versions: versions_link, owners: Some(format!("/api/v1/crates/{}/owners", name)), - reverse_dependencies: format!("/api/v1/crates/{}/reverse_dependencies", name), + reverse_dependencies: format!("/api/v1/crates/{}/reverse_dependencies", name) }, } } @@ -495,8 +455,7 @@ impl Crate { pub fn max_version(&self, conn: &PgConnection) -> CargoResult { use schema::versions::dsl::*; - let vs = Version::belonging_to(self) - .select(num) + let vs = Version::belonging_to(self).select(num) .filter(yanked.eq(false)) .load::(conn)? .into_iter() @@ -508,33 +467,31 @@ impl Crate { let stmt = conn.prepare("SELECT num FROM versions WHERE crate_id = $1 AND yanked = 'f'")?; let rows = stmt.query(&[&self.id])?; - Ok(Version::max(rows.iter() - .map(|r| r.get::<_, String>("num")) - .map(|s| semver::Version::parse(&s).unwrap()))) + Ok(Version::max(rows.iter().map(|r| r.get::<_, String>("num")) + .map(|s| semver::Version::parse(&s).unwrap()))) } pub fn versions(&self, conn: &GenericConnection) -> CargoResult> { let stmt = conn.prepare("SELECT * FROM versions \ WHERE crate_id = $1")?; let rows = stmt.query(&[&self.id])?; - let mut ret = rows.iter() - .map(|r| Model::from_row(&r)) - .collect::>(); + let mut ret = rows.iter().map(|r| { + Model::from_row(&r) + }).collect::>(); ret.sort_by(|a, b| b.num.cmp(&a.num)); Ok(ret) } pub fn owners(&self, conn: &PgConnection) -> CargoResult> { - let base_query = CrateOwner::belonging_to(self).filter(crate_owners::deleted.eq(false)); - let users = base_query - .inner_join(users::table) + let base_query = CrateOwner::belonging_to(self) + .filter(crate_owners::deleted.eq(false)); + let users = base_query.inner_join(users::table) .select(users::all_columns) .filter(crate_owners::owner_kind.eq(OwnerKind::User as i32)) .load(conn)? .into_iter() .map(Owner::User); - let teams = base_query - .inner_join(teams::table) + let teams = base_query.inner_join(teams::table) .select(teams::all_columns) .filter(crate_owners::owner_kind.eq(OwnerKind::Team as i32)) .load(conn)? @@ -567,29 +524,26 @@ impl Crate { Ok(owners) } - pub fn owner_add(&self, - app: &App, - conn: &PgConnection, - req_user: &User, - login: &str) - -> CargoResult<()> { + pub fn owner_add( + &self, + app: &App, + conn: &PgConnection, + req_user: &User, + login: &str, + ) -> CargoResult<()> { let owner = match Owner::find_by_login(conn, login) { - Ok(owner @ Owner::User(_)) => owner, - Ok(Owner::Team(team)) => { - if team.contains_user(app, req_user)? { - Owner::Team(team) - } else { - return Err(human(&format_args!("only members of {} can add it as \ + Ok(owner @ Owner::User(_)) => { owner } + Ok(Owner::Team(team)) => if team.contains_user(app, req_user)? { + Owner::Team(team) + } else { + return Err(human(&format_args!("only members of {} can add it as \ an owner", login))); - } - } - Err(err) => { - if login.contains(':') { - Owner::Team(Team::create(app, conn, login, req_user)?) - } else { - return Err(err); - } - } + }, + Err(err) => if login.contains(':') { + Owner::Team(Team::create(app, conn, login, req_user)?) + } else { + return Err(err); + }, }; let crate_owner = CrateOwner { @@ -598,10 +552,11 @@ impl Crate { created_by: req_user.id, owner_kind: owner.kind() as i32, }; - diesel::insert(&crate_owner.on_conflict(crate_owners::table.primary_key(), - do_update().set(crate_owners::deleted.eq(false)))) - .into(crate_owners::table) - .execute(conn)?; + diesel::insert(&crate_owner.on_conflict( + crate_owners::table.primary_key(), + do_update().set(crate_owners::deleted.eq(false)), + )).into(crate_owners::table) + .execute(conn)?; Ok(()) } @@ -609,14 +564,16 @@ impl Crate { pub fn owner_remove(&self, conn: &PgConnection, _req_user: &User, - login: &str) - -> CargoResult<()> { - let owner = - Owner::find_by_login(conn, login) - .map_err(|_| human(&format_args!("could not find owner with login `{}`", login)))?; - let target = crate_owners::table.find((self.id(), owner.id(), owner.kind() as i32)); - diesel::update(target) - .set(crate_owners::deleted.eq(true)) + login: &str) -> CargoResult<()> { + let owner = Owner::find_by_login(conn, login).map_err(|_| { + human(&format_args!("could not find owner with login `{}`", login)) + })?; + let target = crate_owners::table.find(( + self.id(), + owner.id(), + owner.kind() as i32, + )); + diesel::update(target).set(crate_owners::deleted.eq(true)) .execute(conn)?; Ok(()) } @@ -628,7 +585,7 @@ impl Crate { authors: &[String]) -> CargoResult { if Version::find_by_num(conn, self.id, ver)?.is_some() { - return Err(human(&format_args!("crate version `{}` is already uploaded", ver))); + return Err(human(&format_args!("crate version `{}` is already uploaded", ver))) } Version::insert(conn, self.id, ver, features, authors) } @@ -653,9 +610,7 @@ impl Crate { } pub fn badges(&self, conn: &PgConnection) -> QueryResult> { - badges::table - .filter(badges::crate_id.eq(self.id)) - .load(conn) + badges::table.filter(badges::crate_id.eq(self.id)).load(conn) } /// Returns (dependency, dependent crate name, dependent crate downloads) @@ -672,7 +627,10 @@ impl Crate { } else { rows.get(0).get("total") }; - let vec: Vec<_> = rows.iter().map(|r| Model::from_row(&r)).collect(); + let vec: Vec<_> = rows + .iter() + .map(|r| Model::from_row(&r)) + .collect(); Ok((vec, cnt)) } @@ -695,9 +653,7 @@ impl Model for Crate { max_upload_size: row.get("max_upload_size"), } } - fn table_name(_: Option) -> &'static str { - "crates" - } + fn table_name(_: Option) -> &'static str { "crates" } } /// Handles the `GET /crates` route. @@ -727,9 +683,7 @@ pub fn index(req: &mut Request) -> CargoResult { let q = plainto_tsquery(q_string); query = query.filter(q.matches(crates::textsearchable_index_col)); - query = - query - .select((ALL_COLUMNS, sql::("COUNT(*) OVER()"), crates::name.eq(q_string))); + query = query.select((ALL_COLUMNS, sql::("COUNT(*) OVER()"), crates::name.eq(q_string))); let perfect_match = crates::name.eq(q_string).desc(); if sort == "downloads" { query = query.order((perfect_match, crates::downloads.desc())); @@ -749,34 +703,32 @@ pub fn index(req: &mut Request) -> CargoResult { } if let Some(kw) = params.get("keyword") { - query = query.filter(crates::id.eq_any(crates_keywords::table - .select(crates_keywords::crate_id) - .inner_join(keywords::table) - .filter(::lower(keywords::keyword) - .eq(::lower(kw))))); + query = query.filter(crates::id.eq_any( + crates_keywords::table.select(crates_keywords::crate_id) + .inner_join(keywords::table) + .filter(::lower(keywords::keyword).eq(::lower(kw))) + )); } else if let Some(letter) = params.get("letter") { let pattern = format!("{}%", letter.chars().next().unwrap() .to_lowercase().collect::()); query = query.filter(canon_crate_name(crates::name).like(pattern)); - } else if let Some(user_id) = params.get("user_id").and_then(|s| s.parse::().ok()) { - query = - query.filter(crates::id.eq_any(crate_owners::table - .select(crate_owners::crate_id) - .filter(crate_owners::owner_id.eq(user_id)) - .filter(crate_owners::owner_kind - .eq(OwnerKind::User as i32)))); + } + else if let Some(user_id) = params.get("user_id").and_then(|s| s.parse::().ok()) { + query = query.filter(crates::id.eq_any( + crate_owners::table.select(crate_owners::crate_id) + .filter(crate_owners::owner_id.eq(user_id)) + .filter(crate_owners::owner_kind.eq(OwnerKind::User as i32)) + )); } else if params.get("following").is_some() { - query = query.filter(crates::id.eq_any(follows::table - .select(follows::crate_id) - .filter(follows::user_id - .eq(req.user()?.id)))); + query = query.filter(crates::id.eq_any( + follows::table.select(follows::crate_id) + .filter(follows::user_id.eq(req.user()?.id)) + )); } let data = query.load::<(Crate, i64, bool)>(&*conn)?; let total = data.get(0).map(|&(_, t, _)| t).unwrap_or(0); - let crates = data.iter() - .map(|&(ref c, _, _)| c.clone()) - .collect::>(); + let crates = data.iter().map(|&(ref c, _, _)| c.clone()).collect::>(); let perfect_matches = data.into_iter().map(|(_, _, b)| b).collect::>(); let versions = Version::belonging_to(&crates) @@ -785,33 +737,23 @@ pub fn index(req: &mut Request) -> CargoResult { .into_iter() .map(|versions| Version::max(versions.into_iter().map(|v| v.num))); - let crates = versions - .zip(crates) - .zip(perfect_matches) - .map(|((max_version, krate), perfect_match)| { - // FIXME: If we add crate_id to the Badge enum we can eliminate - // this N+1 - let badges = badges::table - .filter(badges::crate_id.eq(krate.id)) - .load::(&*conn)?; - Ok(krate.minimal_encodable(max_version, Some(badges), perfect_match)) - }) - .collect::>()?; + let crates = versions.zip(crates).zip(perfect_matches).map(|((max_version, krate), perfect_match)| { + // FIXME: If we add crate_id to the Badge enum we can eliminate + // this N+1 + let badges = badges::table.filter(badges::crate_id.eq(krate.id)) + .load::(&*conn)?; + Ok(krate.minimal_encodable(max_version, Some(badges), perfect_match)) + }).collect::>()?; #[derive(RustcEncodable)] - struct R { - crates: Vec, - meta: Meta, - } + struct R { crates: Vec, meta: Meta } #[derive(RustcEncodable)] - struct Meta { - total: i64, - } + struct Meta { total: i64 } Ok(req.json(&R { - crates: crates, - meta: Meta { total: total }, - })) + crates: crates, + meta: Meta { total: total }, + })) } /// Handles the `GET /summary` route. @@ -820,8 +762,7 @@ pub fn summary(req: &mut Request) -> CargoResult { let conn = req.db_conn()?; let num_crates = crates.count().get_result(&*conn)?; - let num_downloads = metadata::table - .select(metadata::total_downloads) + let num_downloads = metadata::table.select(metadata::total_downloads) .get_result(&*conn)?; let encode_crates = |krates: Vec| -> CargoResult> { @@ -832,29 +773,26 @@ pub fn summary(req: &mut Request) -> CargoResult { .into_iter() .map(|versions| Version::max(versions.into_iter().map(|v| v.num))) .zip(krates) - .map(|(max_version, krate)| Ok(krate.minimal_encodable(max_version, None, false))) - .collect() + .map(|(max_version, krate)| { + Ok(krate.minimal_encodable(max_version, None, false)) + }).collect() }; - let new_crates = crates - .order(created_at.desc()) + let new_crates = crates.order(created_at.desc()) .select(ALL_COLUMNS) .limit(10) .load(&*conn)?; - let just_updated = crates - .filter(updated_at.ne(created_at)) + let just_updated = crates.filter(updated_at.ne(created_at)) .order(updated_at.desc()) .select(ALL_COLUMNS) .limit(10) .load(&*conn)?; - let most_downloaded = crates - .order(downloads.desc()) + let most_downloaded = crates.order(downloads.desc()) .select(ALL_COLUMNS) .limit(10) .load(&*conn)?; - let popular_keywords = keywords::table - .order(keywords::crates_cnt.desc()) + let popular_keywords = keywords::table.order(keywords::crates_cnt.desc()) .limit(10) .load(&*conn)? .into_iter() @@ -877,14 +815,14 @@ pub fn summary(req: &mut Request) -> CargoResult { popular_categories: Vec, } Ok(req.json(&R { - num_downloads: num_downloads, - num_crates: num_crates, - new_crates: encode_crates(new_crates)?, - most_downloaded: encode_crates(most_downloaded)?, - just_updated: encode_crates(just_updated)?, - popular_keywords: popular_keywords, - popular_categories: popular_categories, - })) + num_downloads: num_downloads, + num_crates: num_crates, + new_crates: encode_crates(new_crates)?, + most_downloaded: encode_crates(most_downloaded)?, + just_updated: encode_crates(just_updated)?, + popular_keywords: popular_keywords, + popular_categories: popular_categories, + })) } /// Handles the `GET /crates/:crate_id` route. @@ -906,8 +844,7 @@ pub fn show(req: &mut Request) -> CargoResult { .select(categories::all_columns) .load(&*conn)?; - let badges = badges::table - .filter(badges::crate_id.eq(krate.id)) + let badges = badges::table.filter(badges::crate_id.eq(krate.id)) .load(&*conn)?; let max_version = krate.max_version(&conn)?; @@ -919,21 +856,15 @@ pub fn show(req: &mut Request) -> CargoResult { categories: Vec, } Ok(req.json(&R { - krate: krate - .clone() - .encodable(max_version, - Some(ids), - Some(&kws), - Some(&cats), - Some(badges), - false), - versions: versions - .into_iter() - .map(|v| v.encodable(&krate.name)) - .collect(), - keywords: kws.into_iter().map(|k| k.encodable()).collect(), - categories: cats.into_iter().map(|k| k.encodable()).collect(), - })) + krate: krate.clone().encodable( + max_version, Some(ids), Some(&kws), Some(&cats), Some(badges), false + ), + versions: versions.into_iter().map(|v| { + v.encodable(&krate.name) + }).collect(), + keywords: kws.into_iter().map(|k| k.encodable()).collect(), + categories: cats.into_iter().map(|k| k.encodable()).collect(), + })) } /// Handles the `PUT /crates/new` route. @@ -943,18 +874,15 @@ pub fn new(req: &mut Request) -> CargoResult { let name = &*new_crate.name; let vers = &*new_crate.vers; - let features = new_crate - .features - .iter() - .map(|(k, v)| (k[..].to_string(), v.iter().map(|v| v[..].to_string()).collect())) - .collect::>>(); - let keywords = new_crate - .keywords - .as_ref() - .map(|kws| kws.iter().map(|kw| &**kw).collect()) - .unwrap_or_else(Vec::new); - - let categories = new_crate.categories.as_ref().map(|s| &s[..]).unwrap_or(&[]); + let features = new_crate.features.iter().map(|(k, v)| { + (k[..].to_string(), v.iter().map(|v| v[..].to_string()).collect()) + }).collect::>>(); + let keywords = new_crate.keywords.as_ref().map(|kws| { + kws.iter().map(|kw| &**kw).collect() + }).unwrap_or_else(Vec::new); + + let categories = new_crate.categories.as_ref().map(|s| &s[..]) + .unwrap_or(&[]); let categories: Vec<_> = categories.iter().map(|k| &**k).collect(); let conn = req.db_conn()?; @@ -976,21 +904,20 @@ pub fn new(req: &mut Request) -> CargoResult { let owners = krate.owners(&conn)?; if rights(req.app(), &owners, &user)? < Rights::Publish { return Err(human("crate name has already been claimed by \ - another user")); + another user")) } if krate.name != name { - return Err(human(&format_args!("crate was previously named `{}`", krate.name))); + return Err(human(&format_args!("crate was previously named `{}`", krate.name))) } - let length = req.content_length() - .chain_error(|| human("missing header: Content-Length"))?; - let max = krate - .max_upload_size - .map(|m| m as u64) - .unwrap_or(app.config.max_upload_size); + let length = req.content_length().chain_error(|| { + human("missing header: Content-Length") + })?; + let max = krate.max_upload_size.map(|m| m as u64) + .unwrap_or(app.config.max_upload_size); if length > max { - return Err(human(&format_args!("max upload size is: {}", max))); + return Err(human(&format_args!("max upload size is: {}", max))) } // Persist the new version of this crate @@ -1009,7 +936,11 @@ pub fn new(req: &mut Request) -> CargoResult { // Update all badges for this crate, collecting any invalid badges in // order to be able to warn about them - let ignored_invalid_badges = Badge::update_crate(&conn, &krate, new_crate.badges.as_ref())?; + let ignored_invalid_badges = Badge::update_crate( + &conn, + &krate, + new_crate.badges.as_ref() + )?; let max_version = krate.max_version(&conn)?; // Upload the crate, return way to delete the crate from the server @@ -1026,10 +957,9 @@ pub fn new(req: &mut Request) -> CargoResult { deps: git_deps, yanked: Some(false), }; - git::add_crate(&**req.app(), &git_crate) - .chain_error(|| { - internal(&format_args!("could not add crate `{}` to the git repo", name)) - })?; + git::add_crate(&**req.app(), &git_crate).chain_error(|| { + internal(&format_args!("could not add crate `{}` to the git repo", name)) + })?; // Now that we've come this far, we're committed! bomb.path = None; @@ -1045,14 +975,11 @@ pub fn new(req: &mut Request) -> CargoResult { }; #[derive(RustcEncodable)] - struct R<'a> { - krate: EncodableCrate, - warnings: Warnings<'a>, - } + struct R<'a> { krate: EncodableCrate, warnings: Warnings<'a> } Ok(req.json(&R { - krate: krate.minimal_encodable(max_version, None, false), - warnings: warnings, - })) + krate: krate.minimal_encodable(max_version, None, false), + warnings: warnings + })) }) } @@ -1061,20 +988,19 @@ fn parse_new_headers(req: &mut Request) -> CargoResult<(upload::NewCrate, User)> let amt = read_le_u32(req.body())? as u64; let max = req.app().config.max_upload_size; if amt > max { - return Err(human(&format_args!("max upload size is: {}", max))); + return Err(human(&format_args!("max upload size is: {}", max))) } let mut json = vec![0; amt as usize]; read_fill(req.body(), &mut json)?; - let json = String::from_utf8(json) - .map_err(|_| human("json body was not valid utf-8"))?; - let new: upload::NewCrate = - json::decode(&json) - .map_err(|e| human(&format_args!("invalid upload request: {:?}", e)))?; + let json = String::from_utf8(json).map_err(|_| { + human("json body was not valid utf-8") + })?; + let new: upload::NewCrate = json::decode(&json).map_err(|e| { + human(&format_args!("invalid upload request: {:?}", e)) + })?; // Make sure required fields are provided - fn empty(s: Option<&String>) -> bool { - s.map_or(true, |s| s.is_empty()) - } + fn empty(s: Option<&String>) -> bool { s.map_or(true, |s| s.is_empty()) } let mut missing = Vec::new(); if empty(new.description.as_ref()) { @@ -1111,18 +1037,15 @@ pub fn download(req: &mut Request) -> CargoResult { increment_download_counts(req, crate_name, version)?; } - let redirect_url = req.app() - .config - .uploader - .crate_location(crate_name, version) - .ok_or_else(|| human("crate files not found"))?; + let redirect_url = req.app().config.uploader + .crate_location(crate_name, version).ok_or_else(|| + human("crate files not found") + )?; if req.wants_json() { #[derive(RustcEncodable)] - struct R { - url: String, - } - Ok(req.json(&R { url: redirect_url })) + struct R { url: String } + Ok(req.json(&R{ url: redirect_url })) } else { Ok(req.redirect(redirect_url)) } @@ -1132,8 +1055,7 @@ fn increment_download_counts(req: &Request, crate_name: &str, version: &str) -> use self::versions::dsl::*; let conn = req.db_conn()?; - let version_id = versions - .select(id) + let version_id = versions.select(id) .filter(crate_id.eq_any(Crate::by_name(crate_name).select(crates::id))) .filter(num.eq(version)) .first(&*conn)?; @@ -1172,24 +1094,13 @@ pub fn downloads(req: &mut Request) -> CargoResult { .load::(&*conn)?; #[derive(RustcEncodable, Queryable)] - struct ExtraDownload { - date: String, - downloads: i64, - } + struct ExtraDownload { date: String, downloads: i64 } #[derive(RustcEncodable)] - struct R { - version_downloads: Vec, - meta: Meta, - } + struct R { version_downloads: Vec, meta: Meta } #[derive(RustcEncodable)] - struct Meta { - extra_downloads: Vec, - } + struct Meta { extra_downloads: Vec } let meta = Meta { extra_downloads: extra }; - Ok(req.json(&R { - version_downloads: downloads, - meta: meta, - })) + Ok(req.json(&R{ version_downloads: downloads, meta: meta })) } #[derive(Insertable, Queryable, Identifiable, Associations)] @@ -1205,11 +1116,13 @@ fn follow_target(req: &mut Request) -> CargoResult { let user = req.user()?; let conn = req.db_conn()?; let crate_name = &req.params()["crate_id"]; - let crate_id = Crate::by_name(crate_name).select(crates::id).first(&*conn)?; + let crate_id = Crate::by_name(crate_name) + .select(crates::id) + .first(&*conn)?; Ok(Follow { - user_id: user.id, - crate_id: crate_id, - }) + user_id: user.id, + crate_id: crate_id, + }) } /// Handles the `PUT /crates/:crate_id/follow` route. @@ -1220,9 +1133,7 @@ pub fn follow(req: &mut Request) -> CargoResult { .into(follows::table) .execute(&*conn)?; #[derive(RustcEncodable)] - struct R { - ok: bool, - } + struct R { ok: bool } Ok(req.json(&R { ok: true })) } @@ -1232,9 +1143,7 @@ pub fn unfollow(req: &mut Request) -> CargoResult { let conn = req.db_conn()?; diesel::delete(&follow).execute(&*conn)?; #[derive(RustcEncodable)] - struct R { - ok: bool, - } + struct R { ok: bool } Ok(req.json(&R { ok: true })) } @@ -1247,9 +1156,7 @@ pub fn following(req: &mut Request) -> CargoResult { let following = diesel::select(exists(follows::table.find(follow.id()))) .get_result(&*conn)?; #[derive(RustcEncodable)] - struct R { - following: bool, - } + struct R { following: bool } Ok(req.json(&R { following: following })) } @@ -1261,16 +1168,12 @@ pub fn versions(req: &mut Request) -> CargoResult { let tx = req.tx()?; let krate = Crate::find_by_name(tx, crate_name)?; let versions = krate.versions(tx)?; - let versions = versions - .into_iter() - .map(|v| v.encodable(crate_name)) - .collect(); + let versions = versions.into_iter().map(|v| v.encodable(crate_name)) + .collect(); #[derive(RustcEncodable)] - struct R { - versions: Vec, - } - Ok(req.json(&R { versions: versions })) + struct R { versions: Vec } + Ok(req.json(&R{ versions: versions })) } /// Handles the `GET /crates/:crate_id/owners` route. @@ -1278,17 +1181,14 @@ pub fn owners(req: &mut Request) -> CargoResult { let crate_name = &req.params()["crate_id"]; let conn = req.db_conn()?; let krate = Crate::by_name(crate_name).first::(&*conn)?; - let owners = krate - .owners(&conn)? + let owners = krate.owners(&conn)? .into_iter() .map(Owner::encodable) .collect(); #[derive(RustcEncodable)] - struct R { - users: Vec, - } - Ok(req.json(&R { users: owners })) + struct R { users: Vec } + Ok(req.json(&R{ users: owners })) } /// Handles the `PUT /crates/:crate_id/owners` route. @@ -1327,35 +1227,33 @@ fn modify_owners(req: &mut Request, add: bool) -> CargoResult { owners: Option>, } - let request: Request = json::decode(&body) - .map_err(|_| human("invalid json request"))?; + let request: Request = json::decode(&body).map_err(|_| { + human("invalid json request") + })?; - let logins = request - .owners - .or(request.users) - .ok_or_else(|| human("invalid json request"))?; + let logins = request.owners.or(request.users).ok_or_else(|| { + human("invalid json request") + })?; for login in &logins { if add { if owners.iter().any(|owner| owner.login() == *login) { - return Err(human(&format_args!("`{}` is already an owner", login))); + return Err(human(&format_args!("`{}` is already an owner", login))) } krate.owner_add(req.app(), &conn, user, login)?; } else { // Removing the team that gives you rights is prevented because // team members only have Rights::Publish if *login == user.gh_login { - return Err(human("cannot remove yourself as an owner")); + return Err(human("cannot remove yourself as an owner")) } krate.owner_remove(&conn, user, login)?; } } #[derive(RustcEncodable)] - struct R { - ok: bool, - } - Ok(req.json(&R { ok: true })) + struct R { ok: bool } + Ok(req.json(&R{ ok: true })) } /// Handles the `GET /crates/:crate_id/reverse_dependencies` route. @@ -1365,24 +1263,15 @@ pub fn reverse_dependencies(req: &mut Request) -> CargoResult { let krate = Crate::find_by_name(conn, name)?; let (offset, limit) = req.pagination(10, 100)?; let (rev_deps, total) = krate.reverse_dependencies(conn, offset, limit)?; - let rev_deps = rev_deps - .into_iter() + let rev_deps = rev_deps.into_iter() .map(ReverseDependency::encodable) .collect(); #[derive(RustcEncodable)] - struct R { - dependencies: Vec, - meta: Meta, - } + struct R { dependencies: Vec, meta: Meta } #[derive(RustcEncodable)] - struct Meta { - total: i64, - } - Ok(req.json(&R { - dependencies: rev_deps, - meta: Meta { total: total }, - })) + struct Meta { total: i64 } + Ok(req.json(&R{ dependencies: rev_deps, meta: Meta { total: total } })) } use diesel::types::{Text, Date}; diff --git a/src/lib.rs b/src/lib.rs index 0c53049e973..25cf755e746 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,16 +7,11 @@ #![cfg_attr(feature = "clippy", feature(plugin))] #![cfg_attr(feature = "clippy", plugin(clippy))] -#[macro_use] -extern crate diesel; -#[macro_use] -extern crate diesel_codegen; -#[macro_use] -extern crate log; -#[macro_use] -extern crate serde_json; -#[macro_use] -extern crate serde_derive; +#[macro_use] extern crate diesel; +#[macro_use] extern crate diesel_codegen; +#[macro_use] extern crate log; +#[macro_use] extern crate serde_json; +#[macro_use] extern crate serde_derive; extern crate chrono; extern crate curl; extern crate diesel_full_text_search; @@ -114,10 +109,8 @@ pub fn middleware(app: Arc) -> MiddlewareBuilder { api_router.put("/crates/new", C(krate::new)); api_router.get("/crates/:crate_id/:version", C(version::show)); api_router.get("/crates/:crate_id/:version/download", C(krate::download)); - api_router.get("/crates/:crate_id/:version/dependencies", - C(version::dependencies)); - api_router.get("/crates/:crate_id/:version/downloads", - C(version::downloads)); + api_router.get("/crates/:crate_id/:version/dependencies", C(version::dependencies)); + api_router.get("/crates/:crate_id/:version/downloads", C(version::downloads)); api_router.get("/crates/:crate_id/:version/authors", C(version::authors)); api_router.get("/crates/:crate_id/downloads", C(krate::downloads)); api_router.get("/crates/:crate_id/versions", C(krate::versions)); @@ -129,8 +122,7 @@ pub fn middleware(app: Arc) -> MiddlewareBuilder { api_router.delete("/crates/:crate_id/owners", C(krate::remove_owners)); api_router.delete("/crates/:crate_id/:version/yank", C(version::yank)); api_router.put("/crates/:crate_id/:version/unyank", C(version::unyank)); - api_router.get("/crates/:crate_id/reverse_dependencies", - C(krate::reverse_dependencies)); + api_router.get("/crates/:crate_id/reverse_dependencies", C(krate::reverse_dependencies)); api_router.get("/versions", C(version::index)); api_router.get("/versions/:version_id", C(version::show)); api_router.get("/keywords", C(keyword::index)); @@ -177,7 +169,8 @@ pub fn middleware(app: Arc) -> MiddlewareBuilder { m.around(util::Head::default()); m.add(conduit_conditional_get::ConditionalGet); m.add(conduit_cookie::Middleware::new(app.session_key.as_bytes())); - m.add(conduit_cookie::SessionMiddleware::new("cargo_session", env == Env::Production)); + m.add(conduit_cookie::SessionMiddleware::new("cargo_session", + env == Env::Production)); m.add(app::AppMiddleware::new(app)); if env != Env::Test { m.add(db::TransactionMiddleware); @@ -192,7 +185,8 @@ pub fn middleware(app: Arc) -> MiddlewareBuilder { struct DebugMiddleware; impl conduit_middleware::Middleware for DebugMiddleware { - fn before(&self, req: &mut conduit::Request) -> Result<(), Box> { + fn before(&self, req: &mut conduit::Request) + -> Result<(), Box> { println!(" version: {}", req.http_version()); println!(" method: {:?}", req.method()); println!(" scheme: {:?}", req.scheme()); @@ -205,10 +199,9 @@ pub fn middleware(app: Arc) -> MiddlewareBuilder { } Ok(()) } - fn after(&self, - _req: &mut conduit::Request, - res: Result>) - -> Result> { + fn after(&self, _req: &mut conduit::Request, + res: Result>) + -> Result> { res.map(|res| { println!(" <- {:?}", res.status); for (k, v) in &res.headers { @@ -230,7 +223,9 @@ pub fn encode_time(ts: time::Timespec) -> String { pub fn env(s: &str) -> String { dotenv::dotenv().ok(); - ::std::env::var(s).unwrap_or_else(|_| panic!("must have `{}` defined", s)) + ::std::env::var(s).unwrap_or_else(|_| { + panic!("must have `{}` defined", s) + }) } sql_function!(lower, lower_t, (x: ::diesel::types::Text) -> ::diesel::types::Text); diff --git a/src/owner.rs b/src/owner.rs index bf7345deaa8..70faa2d0987 100644 --- a/src/owner.rs +++ b/src/owner.rs @@ -50,6 +50,7 @@ pub struct Team { /// Sugary goodness pub name: Option, pub avatar: Option, + } #[derive(RustcEncodable)] @@ -86,12 +87,10 @@ impl Team { "github" => { // Ok to unwrap since we know one ":" is contained let org = chunks.next().unwrap(); - let team = chunks - .next() - .ok_or_else(|| { - human("missing github team argument; \ + let team = chunks.next().ok_or_else(|| + human("missing github team argument; \ format is github:org:team") - })?; + )?; Team::create_github_team(app, conn, login, org, team, req_user) } _ => { @@ -104,12 +103,8 @@ impl Team { /// Tries to create a Github Team from scratch. Assumes `org` and `team` are /// correctly parsed out of the full `name`. `name` is passed as a /// convenience to avoid rebuilding it. - pub fn create_github_team(app: &App, - conn: &PgConnection, - login: &str, - org_name: &str, - team_name: &str, - req_user: &User) + pub fn create_github_team(app: &App, conn: &PgConnection, login: &str, + org_name: &str, team_name: &str, req_user: &User) -> CargoResult { // GET orgs/:org/teams // check that `team` is the `slug` in results, and grab its data @@ -118,7 +113,7 @@ impl Team { fn whitelist(c: &char) -> bool { match *c { 'a'...'z' | 'A'...'Z' | '0'...'9' | '-' | '_' => false, - _ => true, + _ => true } } @@ -129,9 +124,9 @@ impl Team { #[derive(RustcDecodable)] struct GithubTeam { - slug: String, // the name we want to find - id: i32, // unique GH id (needed for membership queries) - name: Option, // Pretty name + slug: String, // the name we want to find + id: i32, // unique GH id (needed for membership queries) + name: Option, // Pretty name } // FIXME: we just set per_page=100 and don't bother chasing pagination @@ -141,13 +136,11 @@ impl Team { let (handle, data) = http::github(app, &url, &token)?; let teams: Vec = http::parse_github_response(handle, &data)?; - let team = teams - .into_iter() - .find(|team| team.slug == team_name) + let team = teams.into_iter().find(|team| team.slug == team_name) .ok_or_else(|| { - human(&format_args!("could not find the github team {}/{}", + human(&format_args!("could not find the github team {}/{}", org_name, team_name)) - })?; + })?; if !team_with_gh_id_contains_user(app, team.id, req_user)? { return Err(human("only members of a team can add it as an owner")); @@ -188,8 +181,9 @@ impl Team { avatar: avatar, }; - diesel::insert(&new_team.on_conflict(teams::github_id, do_update().set(&new_team))) - .into(teams::table) + diesel::insert( + &new_team.on_conflict(teams::github_id, do_update().set(&new_team)) + ).into(teams::table) .get_result(conn) .map_err(Into::into) } @@ -203,7 +197,8 @@ impl Team { } } -fn team_with_gh_id_contains_user(app: &App, github_id: i32, user: &User) -> CargoResult { +fn team_with_gh_id_contains_user(app: &App, github_id: i32, user: &User) + -> CargoResult { // GET teams/:team_id/memberships/:user_name // check that "state": "active" @@ -219,7 +214,7 @@ fn team_with_gh_id_contains_user(app: &App, github_id: i32, user: &User) -> Carg // Officially how `false` is returned if handle.response_code().unwrap() == 404 { - return Ok(false); + return Ok(false) } let membership: Membership = http::parse_github_response(handle, &resp)?; @@ -240,28 +235,29 @@ impl Model for Team { } } - fn table_name(_: Option) -> &'static str { - "teams" - } + fn table_name(_: Option) -> &'static str { "teams" } } impl Owner { /// Finds the owner by name, failing out if it doesn't exist. /// May be a user's GH login, or a full team name. This is case /// sensitive. - pub fn find_by_login(conn: &PgConnection, name: &str) -> CargoResult { + pub fn find_by_login(conn: &PgConnection, + name: &str) -> CargoResult { if name.contains(':') { - teams::table - .filter(teams::login.eq(name)) + teams::table.filter(teams::login.eq(name)) .first(conn) .map(Owner::Team) - .map_err(|_| human(&format_args!("could not find team with name {}", name))) + .map_err(|_| + human(&format_args!("could not find team with name {}", name)) + ) } else { - users::table - .filter(users::gh_login.eq(name)) + users::table.filter(users::gh_login.eq(name)) .first(conn) .map(Owner::User) - .map_err(|_| human(&format_args!("could not find user with login `{}`", name))) + .map_err(|_| + human(&format_args!("could not find user with login `{}`", name)) + ) } } @@ -288,14 +284,7 @@ impl Owner { pub fn encodable(self) -> EncodableOwner { match self { - Owner::User(User { - id, - email, - name, - gh_login, - gh_avatar, - .. - }) => { + Owner::User(User { id, email, name, gh_login, gh_avatar, .. }) => { let url = format!("https://github.com/{}", gh_login); EncodableOwner { id: id, @@ -307,13 +296,7 @@ impl Owner { kind: String::from("user"), } } - Owner::Team(Team { - id, - name, - login, - avatar, - .. - }) => { + Owner::Team(Team { id, name, login, avatar, .. }) => { let url = { let mut parts = login.split(':'); parts.next(); // discard github @@ -346,17 +329,14 @@ pub fn rights(app: &App, owners: &[Owner], user: &User) -> CargoResult { let mut best = Rights::None; for owner in owners { match *owner { - Owner::User(ref other_user) => { - if other_user.id == user.id { - return Ok(Rights::Full); - } - } - Owner::Team(ref team) => { - if team.contains_user(app, user)? { - best = Rights::Publish; - } - } + Owner::User(ref other_user) => if other_user.id == user.id { + return Ok(Rights::Full); + }, + Owner::Team(ref team) => if team.contains_user(app, user)? { + best = Rights::Publish; + }, } } Ok(best) } + diff --git a/src/tests/all.rs b/src/tests/all.rs index d414b353668..ce5fe12452e 100755 --- a/src/tests/all.rs +++ b/src/tests/all.rs @@ -68,13 +68,9 @@ macro_rules! bad_resp { } #[derive(RustcDecodable, Debug)] -struct Error { - detail: String, -} +struct Error { detail: String } #[derive(RustcDecodable)] -struct Bad { - errors: Vec, -} +struct Bad { errors: Vec } mod badge; mod category; @@ -143,9 +139,7 @@ fn ok_resp(r: &conduit::Response) -> bool { fn bad_resp(r: &mut conduit::Response) -> Option { let bad = json::(r); - if bad.errors.len() == 0 { - return None; - } + if bad.errors.len() == 0 { return None } Some(bad) } @@ -160,24 +154,26 @@ fn json(r: &mut conduit::Response) -> T { let j = fixup(j); let s = j.to_string(); return match json::decode(&s) { - Ok(t) => t, - Err(e) => panic!("failed to decode: {:?}\n{}", e, s), - }; + Ok(t) => t, + Err(e) => panic!("failed to decode: {:?}\n{}", e, s), + }; fn fixup(json: Json) -> Json { match json { Json::Object(object) => { - Json::Object(object - .into_iter() - .map(|(k, v)| { - let k = - if k == "crate" { "krate".to_string() } else { k }; - (k, fixup(v)) - }) - .collect()) + Json::Object(object.into_iter().map(|(k, v)| { + let k = if k == "crate" { + "krate".to_string() + } else { + k + }; + (k, fixup(v)) + }).collect()) + } + Json::Array(list) => { + Json::Array(list.into_iter().map(fixup).collect()) } - Json::Array(list) => Json::Array(list.into_iter().map(fixup).collect()), j => j, } } @@ -292,13 +288,12 @@ impl<'a> CrateBuilder<'a> { } if self.versions.is_empty() { - self.versions - .push("0.99.0".parse().expect("invalid version number")); + self.versions.push("0.99.0".parse().expect("invalid version number")); } for version_num in &self.versions { NewVersion::new(krate.id, version_num, &HashMap::new())? - .save(connection, &[])?; + .save(connection, &[])?; } if !self.keywords.is_empty() { @@ -312,8 +307,8 @@ impl<'a> CrateBuilder<'a> { let name = self.krate.name; self.build(connection) .unwrap_or_else(|e| { - panic!("Unable to create crate {}: {:?}", name, e); - }) + panic!("Unable to create crate {}: {:?}", name, e); + }) } } @@ -346,8 +341,7 @@ fn mock_user(req: &mut Request, u: User) -> User { u.email.as_ref().map(|s| &s[..]), u.name.as_ref().map(|s| &s[..]), u.gh_avatar.as_ref().map(|s| &s[..]), - &u.gh_access_token) - .unwrap(); + &u.gh_access_token).unwrap(); sign_in_as(req, &u); return u; } @@ -366,20 +360,18 @@ fn mock_crate(req: &mut Request, krate: Crate) -> (Crate, Version) { mock_crate_vers(req, krate, &semver::Version::parse("1.0.0").unwrap()) } -fn mock_crate_vers(req: &mut Request, krate: Crate, v: &semver::Version) -> (Crate, Version) { +fn mock_crate_vers(req: &mut Request, krate: Crate, v: &semver::Version) + -> (Crate, Version) { let user = req.extensions().find::().unwrap(); - let mut krate = Crate::find_or_insert(req.tx().unwrap(), - &krate.name, - user.id, - &krate.description, + let mut krate = Crate::find_or_insert(req.tx().unwrap(), &krate.name, + user.id, &krate.description, &krate.homepage, &krate.documentation, &krate.readme, &krate.repository, &krate.license, &None, - krate.max_upload_size) - .unwrap(); + krate.max_upload_size).unwrap(); let v = krate.add_version(req.tx().unwrap(), v, &HashMap::new(), &[]); (krate, v.unwrap()) } @@ -395,35 +387,22 @@ fn new_dependency(conn: &PgConnection, version: &Version, krate: &Crate) -> Depe optional: false, ..Default::default() }; - insert(&dep) - .into(dependencies::table) - .get_result(conn) - .unwrap() + insert(&dep).into(dependencies::table).get_result(conn).unwrap() } -fn mock_dep(req: &mut Request, - version: &Version, - krate: &Crate, - target: Option<&str>) - -> Dependency { +fn mock_dep(req: &mut Request, version: &Version, krate: &Crate, + target: Option<&str>) -> Dependency { Dependency::insert(req.tx().unwrap(), version.id, krate.id, &semver::VersionReq::parse(">= 0").unwrap(), Kind::Normal, - false, - true, - &[], - &target.map(|s| s.to_string())) - .unwrap() + false, true, &[], + &target.map(|s| s.to_string())).unwrap() } fn new_category<'a>(category: &'a str, slug: &'a str) -> NewCategory<'a> { - NewCategory { - category: category, - slug: slug, - ..NewCategory::default() - } + NewCategory { category: category, slug: slug, ..NewCategory::default() } } fn mock_category(req: &mut Request, name: &str, slug: &str) -> Category { @@ -431,8 +410,7 @@ fn mock_category(req: &mut Request, name: &str, slug: &str) -> Category { let stmt = conn.prepare(" \ INSERT INTO categories (category, slug) \ VALUES ($1, $2) \ - RETURNING *") - .unwrap(); + RETURNING *").unwrap(); let rows = stmt.query(&[&name, &slug]).unwrap(); Model::from_row(&rows.iter().next().unwrap()) } @@ -441,7 +419,11 @@ fn logout(req: &mut Request) { req.mut_extensions().pop::(); } -fn request_with_user_and_mock_crate(app: &Arc, user: NewUser, krate: &str) -> MockRequest { +fn request_with_user_and_mock_crate( + app: &Arc, + user: NewUser, + krate: &str, +) -> MockRequest { let mut req = new_req(app.clone(), krate, "1.0.0"); { let conn = app.diesel_database.get().unwrap(); @@ -456,98 +438,89 @@ fn new_req(app: Arc, krate: &str, version: &str) -> MockRequest { new_req_full(app, ::krate(krate), version, Vec::new()) } -fn new_req_full(app: Arc, - krate: Crate, - version: &str, - deps: Vec) - -> MockRequest { +fn new_req_full(app: Arc, krate: Crate, version: &str, + deps: Vec) -> MockRequest { let mut req = ::req(app, Method::Put, "/api/v1/crates/new"); - req.with_body(&new_req_body(krate, version, deps, Vec::new(), Vec::new(), HashMap::new())); + req.with_body(&new_req_body( + krate, version, deps, Vec::new(), Vec::new(), HashMap::new() + )); return req; } -fn new_req_with_keywords(app: Arc, - krate: Crate, - version: &str, - kws: Vec) - -> MockRequest { +fn new_req_with_keywords(app: Arc, krate: Crate, version: &str, + kws: Vec) -> MockRequest { let mut req = ::req(app, Method::Put, "/api/v1/crates/new"); - req.with_body(&new_req_body(krate, version, Vec::new(), kws, Vec::new(), HashMap::new())); + req.with_body(&new_req_body( + krate, version, Vec::new(), kws, Vec::new(), HashMap::new() + )); return req; } -fn new_req_with_categories(app: Arc, - krate: Crate, - version: &str, - cats: Vec) - -> MockRequest { +fn new_req_with_categories(app: Arc, krate: Crate, version: &str, + cats: Vec) -> MockRequest { let mut req = ::req(app, Method::Put, "/api/v1/crates/new"); - req.with_body(&new_req_body(krate, version, Vec::new(), Vec::new(), cats, HashMap::new())); + req.with_body(&new_req_body( + krate, version, Vec::new(), Vec::new(), cats, HashMap::new() + )); return req; } -fn new_req_with_badges(app: Arc, - krate: Crate, - version: &str, +fn new_req_with_badges(app: Arc, krate: Crate, version: &str, badges: HashMap>) -> MockRequest { let mut req = ::req(app, Method::Put, "/api/v1/crates/new"); - req.with_body(&new_req_body(krate, version, Vec::new(), Vec::new(), Vec::new(), badges)); + req.with_body(&new_req_body( + krate, version, Vec::new(), Vec::new(), Vec::new(), badges + )); return req; } fn new_req_body_version_2(krate: Crate) -> Vec { - new_req_body(krate, - "2.0.0", - Vec::new(), - Vec::new(), - Vec::new(), - HashMap::new()) -} - -fn new_req_body(krate: Crate, - version: &str, - deps: Vec, - kws: Vec, - cats: Vec, - badges: HashMap>) - -> Vec { + new_req_body( + krate, "2.0.0", Vec::new(), Vec::new(), Vec::new(), HashMap::new() + ) +} + +fn new_req_body(krate: Crate, version: &str, deps: Vec, + kws: Vec, cats: Vec, + badges: HashMap>) -> Vec { let kws = kws.into_iter().map(u::Keyword).collect(); let cats = cats.into_iter().map(u::Category).collect(); new_crate_to_body(&u::NewCrate { - name: u::CrateName(krate.name), - vers: u::CrateVersion(semver::Version::parse(version).unwrap()), - features: HashMap::new(), - deps: deps, - authors: vec!["foo".to_string()], - description: Some("description".to_string()), - homepage: krate.homepage, - documentation: krate.documentation, - readme: krate.readme, - keywords: Some(u::KeywordList(kws)), - categories: Some(u::CategoryList(cats)), - license: Some("MIT".to_string()), - license_file: None, - repository: krate.repository, - badges: Some(badges), - }, - &[]) + name: u::CrateName(krate.name), + vers: u::CrateVersion(semver::Version::parse(version).unwrap()), + features: HashMap::new(), + deps: deps, + authors: vec!["foo".to_string()], + description: Some("description".to_string()), + homepage: krate.homepage, + documentation: krate.documentation, + readme: krate.readme, + keywords: Some(u::KeywordList(kws)), + categories: Some(u::CategoryList(cats)), + license: Some("MIT".to_string()), + license_file: None, + repository: krate.repository, + badges: Some(badges), + }, &[]) } fn new_crate_to_body(new_crate: &u::NewCrate, krate: &[u8]) -> Vec { let json = json::encode(&new_crate).unwrap(); let mut body = Vec::new(); - body.extend([(json.len() >> 0) as u8, - (json.len() >> 8) as u8, - (json.len() >> 16) as u8, - (json.len() >> 24) as u8] - .iter() - .cloned()); + body.extend([ + (json.len() >> 0) as u8, + (json.len() >> 8) as u8, + (json.len() >> 16) as u8, + (json.len() >> 24) as u8, + ].iter().cloned()); body.extend(json.as_bytes().iter().cloned()); - body.extend(&[(krate.len() >> 0) as u8, - (krate.len() >> 8) as u8, - (krate.len() >> 16) as u8, - (krate.len() >> 24) as u8]); + body.extend(&[ + (krate.len() >> 0) as u8, + (krate.len() >> 8) as u8, + (krate.len() >> 16) as u8, + (krate.len() >> 24) as u8, + ]); body.extend(krate); body } diff --git a/src/tests/badge.rs b/src/tests/badge.rs index d094e6fedd3..df997918390 100644 --- a/src/tests/badge.rs +++ b/src/tests/badge.rs @@ -27,8 +27,11 @@ fn set_up() -> (Arc, Crate, BadgeRef) { let krate = { let conn = app.diesel_database.get().unwrap(); - let u = ::new_user("foo").create_or_update(&conn).unwrap(); - ::CrateBuilder::new("badged_crate", u.id).expect_build(&conn) + let u = ::new_user("foo") + .create_or_update(&conn) + .unwrap(); + ::CrateBuilder::new("badged_crate", u.id) + .expect_build(&conn) }; let appveyor = Badge::Appveyor { @@ -37,36 +40,60 @@ fn set_up() -> (Arc, Crate, BadgeRef) { repository: String::from("rust-lang/cargo"), }; let mut badge_attributes_appveyor = HashMap::new(); - badge_attributes_appveyor.insert(String::from("service"), String::from("github")); - badge_attributes_appveyor.insert(String::from("repository"), String::from("rust-lang/cargo")); + badge_attributes_appveyor.insert( + String::from("service"), + String::from("github") + ); + badge_attributes_appveyor.insert( + String::from("repository"), + String::from("rust-lang/cargo") + ); let travis_ci = Badge::TravisCi { branch: Some(String::from("beta")), repository: String::from("rust-lang/rust"), }; let mut badge_attributes_travis_ci = HashMap::new(); - badge_attributes_travis_ci.insert(String::from("branch"), String::from("beta")); - badge_attributes_travis_ci.insert(String::from("repository"), String::from("rust-lang/rust")); + badge_attributes_travis_ci.insert( + String::from("branch"), + String::from("beta") + ); + badge_attributes_travis_ci.insert( + String::from("repository"), + String::from("rust-lang/rust") + ); let gitlab = Badge::GitLab { branch: Some(String::from("beta")), repository: String::from("rust-lang/rust"), }; let mut badge_attributes_gitlab = HashMap::new(); - badge_attributes_gitlab.insert(String::from("branch"), String::from("beta")); - badge_attributes_gitlab.insert(String::from("repository"), String::from("rust-lang/rust")); - - let isitmaintained_issue_resolution = - Badge::IsItMaintainedIssueResolution { repository: String::from("rust-lang/rust") }; + badge_attributes_gitlab.insert( + String::from("branch"), + String::from("beta") + ); + badge_attributes_gitlab.insert( + String::from("repository"), + String::from("rust-lang/rust") + ); + + let isitmaintained_issue_resolution = Badge::IsItMaintainedIssueResolution { + repository: String::from("rust-lang/rust"), + }; let mut badge_attributes_isitmaintained_issue_resolution = HashMap::new(); - badge_attributes_isitmaintained_issue_resolution - .insert(String::from("repository"), String::from("rust-lang/rust")); + badge_attributes_isitmaintained_issue_resolution.insert( + String::from("repository"), + String::from("rust-lang/rust") + ); - let isitmaintained_open_issues = - Badge::IsItMaintainedOpenIssues { repository: String::from("rust-lang/rust") }; + let isitmaintained_open_issues = Badge::IsItMaintainedOpenIssues { + repository: String::from("rust-lang/rust"), + }; let mut badge_attributes_isitmaintained_open_issues = HashMap::new(); - badge_attributes_isitmaintained_open_issues - .insert(String::from("repository"), String::from("rust-lang/rust")); + badge_attributes_isitmaintained_open_issues.insert( + String::from("repository"), + String::from("rust-lang/rust") + ); let codecov = Badge::Codecov { service: Some(String::from("github")), @@ -74,9 +101,18 @@ fn set_up() -> (Arc, Crate, BadgeRef) { repository: String::from("rust-lang/rust"), }; let mut badge_attributes_codecov = HashMap::new(); - badge_attributes_codecov.insert(String::from("branch"), String::from("beta")); - badge_attributes_codecov.insert(String::from("repository"), String::from("rust-lang/rust")); - badge_attributes_codecov.insert(String::from("service"), String::from("github")); + badge_attributes_codecov.insert( + String::from("branch"), + String::from("beta") + ); + badge_attributes_codecov.insert( + String::from("repository"), + String::from("rust-lang/rust") + ); + badge_attributes_codecov.insert( + String::from("service"), + String::from("github") + ); let coveralls = Badge::Coveralls { service: Some(String::from("github")), @@ -84,9 +120,18 @@ fn set_up() -> (Arc, Crate, BadgeRef) { repository: String::from("rust-lang/rust"), }; let mut badge_attributes_coveralls = HashMap::new(); - badge_attributes_coveralls.insert(String::from("branch"), String::from("beta")); - badge_attributes_coveralls.insert(String::from("repository"), String::from("rust-lang/rust")); - badge_attributes_coveralls.insert(String::from("service"), String::from("github")); + badge_attributes_coveralls.insert( + String::from("branch"), + String::from("beta") + ); + badge_attributes_coveralls.insert( + String::from("repository"), + String::from("rust-lang/rust") + ); + badge_attributes_coveralls.insert( + String::from("service"), + String::from("github") + ); let badges = BadgeRef { appveyor: appveyor, @@ -96,8 +141,7 @@ fn set_up() -> (Arc, Crate, BadgeRef) { gitlab: gitlab, gitlab_attributes: badge_attributes_gitlab, isitmaintained_issue_resolution: isitmaintained_issue_resolution, - isitmaintained_issue_resolution_attributes: - badge_attributes_isitmaintained_issue_resolution, + isitmaintained_issue_resolution_attributes: badge_attributes_isitmaintained_issue_resolution, isitmaintained_open_issues: isitmaintained_open_issues, isitmaintained_open_issues_attributes: badge_attributes_isitmaintained_open_issues, codecov: codecov, @@ -126,7 +170,10 @@ fn update_add_appveyor() { let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); - badges.insert(String::from("appveyor"), test_badges.appveyor_attributes); + badges.insert( + String::from("appveyor"), + test_badges.appveyor_attributes + ); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.appveyor]); } @@ -138,7 +185,10 @@ fn update_add_travis_ci() { let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); - badges.insert(String::from("travis-ci"), test_badges.travis_ci_attributes); + badges.insert( + String::from("travis-ci"), + test_badges.travis_ci_attributes + ); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.travis_ci]); } @@ -150,7 +200,10 @@ fn update_add_gitlab() { let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); - badges.insert(String::from("gitlab"), test_badges.gitlab_attributes); + badges.insert( + String::from("gitlab"), + test_badges.gitlab_attributes + ); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.gitlab]); } @@ -162,11 +215,12 @@ fn update_add_isitmaintained_issue_resolution() { let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); - badges.insert(String::from("is-it-maintained-issue-resolution"), - test_badges.isitmaintained_issue_resolution_attributes); + badges.insert( + String::from("is-it-maintained-issue-resolution"), + test_badges.isitmaintained_issue_resolution_attributes + ); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); - assert_eq!(krate.badges(&conn).unwrap(), - vec![test_badges.isitmaintained_issue_resolution]); + assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.isitmaintained_issue_resolution]); } #[test] @@ -176,11 +230,12 @@ fn update_add_isitmaintained_open_issues() { let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); - badges.insert(String::from("is-it-maintained-open-issues"), - test_badges.isitmaintained_open_issues_attributes); + badges.insert( + String::from("is-it-maintained-open-issues"), + test_badges.isitmaintained_open_issues_attributes + ); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); - assert_eq!(krate.badges(&conn).unwrap(), - vec![test_badges.isitmaintained_open_issues]); + assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.isitmaintained_open_issues]); } #[test] @@ -190,7 +245,10 @@ fn update_add_codecov() { let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); - badges.insert(String::from("codecov"), test_badges.codecov_attributes); + badges.insert( + String::from("codecov"), + test_badges.codecov_attributes + ); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.codecov]); } @@ -202,7 +260,10 @@ fn update_add_coveralls() { let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); - badges.insert(String::from("coveralls"), test_badges.coveralls_attributes); + badges.insert( + String::from("coveralls"), + test_badges.coveralls_attributes + ); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.coveralls]); } @@ -215,14 +276,19 @@ fn replace_badge() { // Add a badge let mut badges = HashMap::new(); - badges.insert(String::from("gitlab"), test_badges.gitlab_attributes); + badges.insert( + String::from("gitlab"), + test_badges.gitlab_attributes + ); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.gitlab]); // Replace with another badge badges.clear(); - badges.insert(String::from("travis-ci"), - test_badges.travis_ci_attributes.clone()); + badges.insert( + String::from("travis-ci"), + test_badges.travis_ci_attributes.clone() + ); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.travis_ci]); } @@ -235,7 +301,10 @@ fn update_attributes() { // Add a travis-ci badge let mut badges = HashMap::new(); - badges.insert(String::from("travis-ci"), test_badges.travis_ci_attributes); + badges.insert( + String::from("travis-ci"), + test_badges.travis_ci_attributes + ); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); let current_badges = krate.badges(&conn).unwrap(); assert_eq!(current_badges.len(), 1); @@ -248,9 +317,14 @@ fn update_attributes() { repository: String::from("rust-lang/rust"), }; let mut badge_attributes_travis_ci2 = HashMap::new(); - badge_attributes_travis_ci2.insert(String::from("repository"), String::from("rust-lang/rust")); - badges.insert(String::from("travis-ci"), - badge_attributes_travis_ci2.clone()); + badge_attributes_travis_ci2.insert( + String::from("repository"), + String::from("rust-lang/rust") + ); + badges.insert( + String::from("travis-ci"), + badge_attributes_travis_ci2.clone() + ); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); let current_badges = krate.badges(&conn).unwrap(); assert_eq!(current_badges.len(), 1); @@ -266,9 +340,18 @@ fn clear_badges() { let mut badges = HashMap::new(); // Adding 3 badges - badges.insert(String::from("appveyor"), test_badges.appveyor_attributes); - badges.insert(String::from("travis-ci"), test_badges.travis_ci_attributes); - badges.insert(String::from("gitlab"), test_badges.gitlab_attributes); + badges.insert( + String::from("appveyor"), + test_badges.appveyor_attributes + ); + badges.insert( + String::from("travis-ci"), + test_badges.travis_ci_attributes + ); + badges.insert( + String::from("gitlab"), + test_badges.gitlab_attributes + ); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); let current_badges = krate.badges(&conn).unwrap(); @@ -293,8 +376,14 @@ fn appveyor_extra_keys() { // Extra invalid keys are fine, they just get ignored let mut appveyor_attributes = test_badges.appveyor_attributes.clone(); - appveyor_attributes.insert(String::from("extra"), String::from("info")); - badges.insert(String::from("appveyor"), test_badges.appveyor_attributes); + appveyor_attributes.insert( + String::from("extra"), + String::from("info") + ); + badges.insert( + String::from("appveyor"), + test_badges.appveyor_attributes + ); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.appveyor]); @@ -310,7 +399,10 @@ fn travis_ci_required_keys() { // Repository is a required key test_badges.travis_ci_attributes.remove("repository"); - badges.insert(String::from("travis-ci"), test_badges.travis_ci_attributes); + badges.insert( + String::from("travis-ci"), + test_badges.travis_ci_attributes + ); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); @@ -328,7 +420,10 @@ fn gitlab_required_keys() { // Repository is a required key test_badges.gitlab_attributes.remove("repository"); - badges.insert(String::from("gitlab"), test_badges.gitlab_attributes); + badges.insert( + String::from("gitlab"), + test_badges.gitlab_attributes + ); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); @@ -345,11 +440,11 @@ fn isitmaintained_issue_resolution_required_keys() { let mut badges = HashMap::new(); // Repository is a required key - test_badges - .isitmaintained_issue_resolution_attributes - .remove("repository"); - badges.insert(String::from("isitmaintained_issue_resolution"), - test_badges.isitmaintained_issue_resolution_attributes); + test_badges.isitmaintained_issue_resolution_attributes.remove("repository"); + badges.insert( + String::from("isitmaintained_issue_resolution"), + test_badges.isitmaintained_issue_resolution_attributes + ); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); @@ -366,11 +461,11 @@ fn isitmaintained_open_issues_required_keys() { let mut badges = HashMap::new(); // Repository is a required key - test_badges - .isitmaintained_open_issues_attributes - .remove("repository"); - badges.insert(String::from("isitmaintained_open_issues"), - test_badges.isitmaintained_open_issues_attributes); + test_badges.isitmaintained_open_issues_attributes.remove("repository"); + badges.insert( + String::from("isitmaintained_open_issues"), + test_badges.isitmaintained_open_issues_attributes + ); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); @@ -388,7 +483,10 @@ fn codecov_required_keys() { // Repository is a required key test_badges.codecov_attributes.remove("repository"); - badges.insert(String::from("codecov"), test_badges.codecov_attributes); + badges.insert( + String::from("codecov"), + test_badges.codecov_attributes + ); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); @@ -406,7 +504,10 @@ fn coveralls_required_keys() { // Repository is a required key test_badges.coveralls_attributes.remove("repository"); - badges.insert(String::from("coveralls"), test_badges.coveralls_attributes); + badges.insert( + String::from("coveralls"), + test_badges.coveralls_attributes + ); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); @@ -424,9 +525,14 @@ fn unknown_badge() { // This is not a badge that crates.io knows about let mut invalid_attributes = HashMap::new(); - invalid_attributes.insert(String::from("not-a-badge-attribute"), - String::from("not-a-badge-value")); - badges.insert(String::from("not-a-badge"), invalid_attributes); + invalid_attributes.insert( + String::from("not-a-badge-attribute"), + String::from("not-a-badge-value") + ); + badges.insert( + String::from("not-a-badge"), + invalid_attributes + ); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); diff --git a/src/tests/category.rs b/src/tests/category.rs index 9c30335fe20..b1beb4a1f3b 100644 --- a/src/tests/category.rs +++ b/src/tests/category.rs @@ -5,21 +5,14 @@ use cargo_registry::db::RequestTransaction; use cargo_registry::category::{Category, EncodableCategory, EncodableCategoryWithSubcategories}; #[derive(RustcDecodable)] -struct CategoryList { - categories: Vec, - meta: CategoryMeta, -} +struct CategoryList { categories: Vec, meta: CategoryMeta } #[derive(RustcDecodable)] -struct CategoryMeta { - total: i32, -} +struct CategoryMeta { total: i32 } #[derive(RustcDecodable)] -struct GoodCategory { - category: EncodableCategory, -} +struct GoodCategory { category: EncodableCategory } #[derive(RustcDecodable)] struct CategoryWithSubcategories { - category: EncodableCategoryWithSubcategories, + category: EncodableCategoryWithSubcategories } #[test] @@ -93,7 +86,9 @@ fn update_crate() { assert_eq!(cnt(&mut req, "category-2"), 0); // Replacing one category with another - Category::update_crate_old(req.tx().unwrap(), &krate, &["category-2".to_string()]).unwrap(); + Category::update_crate_old( + req.tx().unwrap(), &krate, &["category-2".to_string()] + ).unwrap(); assert_eq!(cnt(&mut req, "cat1"), 0); assert_eq!(cnt(&mut req, "category-2"), 1); @@ -103,10 +98,9 @@ fn update_crate() { assert_eq!(cnt(&mut req, "category-2"), 0); // Adding 2 categories - Category::update_crate_old(req.tx().unwrap(), - &krate, - &["cat1".to_string(), "category-2".to_string()]) - .unwrap(); + Category::update_crate_old( + req.tx().unwrap(), &krate, &["cat1".to_string(), + "category-2".to_string()]).unwrap(); assert_eq!(cnt(&mut req, "cat1"), 1); assert_eq!(cnt(&mut req, "category-2"), 1); @@ -116,11 +110,10 @@ fn update_crate() { assert_eq!(cnt(&mut req, "category-2"), 0); // Attempting to add one valid category and one invalid category - let invalid_categories = Category::update_crate_old(req.tx().unwrap(), - &krate, - &["cat1".to_string(), - "catnope".to_string()]) - .unwrap(); + let invalid_categories = Category::update_crate_old( + req.tx().unwrap(), &krate, &["cat1".to_string(), + "catnope".to_string()] + ).unwrap(); assert_eq!(invalid_categories, vec!["catnope".to_string()]); assert_eq!(cnt(&mut req, "cat1"), 1); assert_eq!(cnt(&mut req, "category-2"), 0); @@ -134,16 +127,17 @@ fn update_crate() { assert_eq!(json.meta.total, 2); // Attempting to add a category by display text; must use slug - Category::update_crate_old(req.tx().unwrap(), &krate, &["Category 2".to_string()]).unwrap(); + Category::update_crate_old( + req.tx().unwrap(), &krate, &["Category 2".to_string()] + ).unwrap(); assert_eq!(cnt(&mut req, "cat1"), 0); assert_eq!(cnt(&mut req, "category-2"), 0); // Add a category and its subcategory ::mock_category(&mut req, "cat1::bar", "cat1::bar"); - Category::update_crate_old(req.tx().unwrap(), - &krate, - &["cat1".to_string(), "cat1::bar".to_string()]) - .unwrap(); + Category::update_crate_old( + req.tx().unwrap(), &krate, &["cat1".to_string(), + "cat1::bar".to_string()]).unwrap(); assert_eq!(cnt(&mut req, "cat1"), 1); assert_eq!(cnt(&mut req, "cat1::bar"), 1); assert_eq!(cnt(&mut req, "category-2"), 0); diff --git a/src/tests/git.rs b/src/tests/git.rs index bd2309fd66d..feac51e3177 100644 --- a/src/tests/git.rs +++ b/src/tests/git.rs @@ -8,25 +8,20 @@ use git2; use url::Url; fn root() -> PathBuf { - env::current_dir() - .unwrap() - .join("tmp") - .join(thread::current().name().unwrap()) + env::current_dir().unwrap().join("tmp").join(thread::current().name().unwrap()) } -pub fn checkout() -> PathBuf { - root().join("checkout") -} -pub fn bare() -> PathBuf { - root().join("bare") -} +pub fn checkout() -> PathBuf { root().join("checkout") } +pub fn bare() -> PathBuf { root().join("bare") } pub fn init() { static INIT: Once = ONCE_INIT; let _ = fs::remove_dir_all(&checkout()); let _ = fs::remove_dir_all(&bare()); - INIT.call_once(|| { fs::create_dir_all(root().parent().unwrap()).unwrap(); }); + INIT.call_once(|| { + fs::create_dir_all(root().parent().unwrap()).unwrap(); + }); // Prepare a bare remote repo { @@ -43,9 +38,7 @@ pub fn init() { // Setup the `origin` remote checkout.remote_set_url("origin", &url).unwrap(); checkout.remote_set_pushurl("origin", Some(&url)).unwrap(); - checkout - .remote_add_push("origin", "refs/heads/master") - .unwrap(); + checkout.remote_add_push("origin", "refs/heads/master").unwrap(); // Create an empty initial commit let mut config = checkout.config().unwrap(); @@ -55,9 +48,9 @@ pub fn init() { let id = index.write_tree().unwrap(); let tree = checkout.find_tree(id).unwrap(); let sig = checkout.signature().unwrap(); - checkout - .commit(Some("HEAD"), &sig, &sig, "Initial Commit", &tree, &[]) - .unwrap(); + checkout.commit(Some("HEAD"), &sig, &sig, + "Initial Commit", + &tree, &[]).unwrap(); // Push the commit to the remote repo let mut origin = checkout.find_remote("origin").unwrap(); diff --git a/src/tests/keyword.rs b/src/tests/keyword.rs index 980615800d9..8d78f89f049 100644 --- a/src/tests/keyword.rs +++ b/src/tests/keyword.rs @@ -4,18 +4,11 @@ use conduit_test::MockRequest; use cargo_registry::keyword::{Keyword, EncodableKeyword}; #[derive(RustcDecodable)] -struct KeywordList { - keywords: Vec, - meta: KeywordMeta, -} +struct KeywordList { keywords: Vec, meta: KeywordMeta } #[derive(RustcDecodable)] -struct KeywordMeta { - total: i32, -} +struct KeywordMeta { total: i32 } #[derive(RustcDecodable)] -struct GoodKeyword { - keyword: EncodableKeyword, -} +struct GoodKeyword { keyword: EncodableKeyword } #[test] fn index() { @@ -79,9 +72,12 @@ fn update_crate() { let krate = { let conn = app.diesel_database.get().unwrap(); - let u = ::new_user("foo").create_or_update(&conn).unwrap(); + let u = ::new_user("foo") + .create_or_update(&conn) + .unwrap(); Keyword::find_or_create_all(&conn, &["kw1", "kw2"]).unwrap(); - ::CrateBuilder::new("fookey", u.id).expect_build(&conn) + ::CrateBuilder::new("fookey", u.id) + .expect_build(&conn) }; { diff --git a/src/tests/krate.rs b/src/tests/krate.rs index 2b10afc33a1..98f2838bd2f 100644 --- a/src/tests/krate.rs +++ b/src/tests/krate.rs @@ -20,47 +20,23 @@ use cargo_registry::version::EncodableVersion; use cargo_registry::category::Category; #[derive(RustcDecodable)] -struct CrateList { - crates: Vec, - meta: CrateMeta, -} +struct CrateList { crates: Vec, meta: CrateMeta } #[derive(RustcDecodable)] -struct VersionsList { - versions: Vec, -} +struct VersionsList { versions: Vec } #[derive(RustcDecodable)] -struct CrateMeta { - total: i32, -} +struct CrateMeta { total: i32 } #[derive(RustcDecodable)] -struct Warnings { - invalid_categories: Vec, - invalid_badges: Vec, -} +struct Warnings { invalid_categories: Vec, invalid_badges: Vec } #[derive(RustcDecodable)] -struct GoodCrate { - krate: EncodableCrate, - warnings: Warnings, -} +struct GoodCrate { krate: EncodableCrate, warnings: Warnings } #[derive(RustcDecodable)] -struct CrateResponse { - krate: EncodableCrate, - versions: Vec, - keywords: Vec, -} +struct CrateResponse { krate: EncodableCrate, versions: Vec, keywords: Vec } #[derive(RustcDecodable)] -struct Deps { - dependencies: Vec, -} +struct Deps { dependencies: Vec } #[derive(RustcDecodable)] -struct RevDeps { - dependencies: Vec, - meta: CrateMeta, -} +struct RevDeps { dependencies: Vec, meta: CrateMeta } #[derive(RustcDecodable)] -struct Downloads { - version_downloads: Vec, -} +struct Downloads { version_downloads: Vec } fn new_crate(name: &str) -> u::NewCrate { u::NewCrate { @@ -93,8 +69,11 @@ fn index() { let krate = { let conn = app.diesel_database.get().unwrap(); - let u = ::new_user("foo").create_or_update(&conn).unwrap(); - ::CrateBuilder::new("fooindex", u.id).expect_build(&conn) + let u = ::new_user("foo") + .create_or_update(&conn) + .unwrap(); + ::CrateBuilder::new("fooindex", u.id) + .expect_build(&conn) }; let mut response = ok_resp!(middle.call(&mut req)); @@ -114,7 +93,9 @@ fn index_queries() { let krate2; { let conn = app.diesel_database.get().unwrap(); - u = ::new_user("foo").create_or_update(&conn).unwrap(); + u = ::new_user("foo") + .create_or_update(&conn) + .unwrap(); krate = ::CrateBuilder::new("foo_index_queries", u.id) .readme("readme") @@ -174,12 +155,8 @@ fn index_queries() { { let conn = app.diesel_database.get().unwrap(); - ::new_category("Category 1", "cat1") - .find_or_create(&conn) - .unwrap(); - ::new_category("Category 1::Ba'r", "cat1::bar") - .find_or_create(&conn) - .unwrap(); + ::new_category("Category 1", "cat1").find_or_create(&conn).unwrap(); + ::new_category("Category 1::Ba'r", "cat1::bar").find_or_create(&conn).unwrap(); Category::update_crate(&conn, &krate, &["cat1"]).unwrap(); Category::update_crate(&conn, &krate2, &["cat1::bar"]).unwrap(); } @@ -358,8 +335,7 @@ fn show() { assert_eq!(json.versions[0].num, "1.0.0"); let suffix = "/api/v1/crates/foo_show/1.0.0/download"; assert!(json.versions[0].dl_path.ends_with(suffix), - "bad suffix {}", - json.versions[0].dl_path); + "bad suffix {}", json.versions[0].dl_path); assert_eq!(1, json.keywords.len()); assert_eq!("kw1", json.keywords[0].id); @@ -419,8 +395,7 @@ fn new_bad_names() { ::mock_user(&mut req, ::user("foo")); let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("invalid crate name"), - "{:?}", - json.errors); + "{:?}", json.errors); } bad_name(""); @@ -446,9 +421,7 @@ fn new_krate_with_reserved_name() { let mut req = ::new_req(app, name, "1.0.0"); ::mock_user(&mut req, ::user("foo")); let json = bad_resp!(middle.call(&mut req)); - assert!(json.errors[0] - .detail - .contains("cannot upload a crate with a reserved name")); + assert!(json.errors[0].detail.contains("cannot upload a crate with a reserved name")); } test_bad_name("std"); @@ -495,10 +468,7 @@ fn new_krate_with_dependency() { let path = ::git::checkout().join("ne/w_/new_dep"); assert!(path.exists()); let mut contents = String::new(); - File::open(&path) - .unwrap() - .read_to_string(&mut contents) - .unwrap(); + File::open(&path).unwrap().read_to_string(&mut contents).unwrap(); let p: git::Crate = json::decode(&contents).unwrap(); assert_eq!(p.name, "new_dep"); assert_eq!(p.vers, "1.0.0"); @@ -509,15 +479,17 @@ fn new_krate_with_dependency() { #[test] fn new_krate_non_canon_crate_name_dependencies() { let (_b, app, middle) = ::app(); - let deps = vec![u::CrateDependency { - name: u::CrateName("foo-dep".to_string()), - optional: false, - default_features: true, - features: Vec::new(), - version_req: u::CrateVersionReq(semver::VersionReq::parse(">= 0").unwrap()), - target: None, - kind: None, - }]; + let deps = vec![ + u::CrateDependency { + name: u::CrateName("foo-dep".to_string()), + optional: false, + default_features: true, + features: Vec::new(), + version_req: u::CrateVersionReq(semver::VersionReq::parse(">= 0").unwrap()), + target: None, + kind: None, + }, + ]; let mut req = ::new_req_full(app.clone(), ::krate("new_dep"), "1.0.0", deps); { let conn = app.diesel_database.get().unwrap(); @@ -551,9 +523,7 @@ fn new_krate_with_wildcard_dependency() { ::CrateBuilder::new("foo_wild", user.id).expect_build(&conn); } let json = bad_resp!(middle.call(&mut req)); - assert!(json.errors[0].detail.contains("dependency constraints"), - "{:?}", - json.errors); + assert!(json.errors[0].detail.contains("dependency constraints"), "{:?}", json.errors); } #[test] @@ -593,8 +563,7 @@ fn new_krate_wrong_user() { let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("another user"), - "{:?}", - json.errors); + "{:?}", json.errors); } #[test] @@ -606,25 +575,20 @@ fn new_krate_bad_name() { ::sign_in(&mut req, &app); let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("invalid crate name"), - "{:?}", - json.errors); + "{:?}", json.errors); } { let mut req = ::new_req(app.clone(), "áccênts", "2.0.0"); ::sign_in(&mut req, &app); let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("invalid crate name"), - "{:?}", - json.errors); + "{:?}", json.errors); } } #[test] fn new_crate_owner() { - #[derive(RustcDecodable)] - struct O { - ok: bool, - } + #[derive(RustcDecodable)] struct O { ok: bool } let (_b, app, middle) = ::app(); @@ -642,26 +606,26 @@ fn new_crate_owner() { // Flag the second user as an owner let body = r#"{"users":["bar"]}"#; let mut response = ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_owner/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); assert!(::json::(&mut response).ok); bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_owner/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); // Make sure this shows up as one of their crates. let query = format!("user_id={}", u2.id); let mut response = ok_resp!(middle.call(req.with_path("/api/v1/crates") - .with_method(Method::Get) - .with_query(&query))); + .with_method(Method::Get) + .with_query(&query))); assert_eq!(::json::(&mut response).crates.len(), 1); // And upload a new crate as the first user let body = ::new_req_body_version_2(::krate("foo_owner")); ::sign_in_as(&mut req, &u2); let mut response = ok_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_method(Method::Put) - .with_body(&body))); + .with_method(Method::Put) + .with_body(&body))); ::json::(&mut response); } @@ -715,8 +679,7 @@ fn new_krate_duplicate_version() { } let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("already uploaded"), - "{:?}", - json.errors); + "{:?}", json.errors); } #[test] @@ -731,8 +694,7 @@ fn new_crate_similar_name() { } let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("previously named"), - "{:?}", - json.errors); + "{:?}", json.errors); } #[test] @@ -747,8 +709,7 @@ fn new_crate_similar_name_hyphen() { } let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("previously named"), - "{:?}", - json.errors); + "{:?}", json.errors); } #[test] @@ -763,8 +724,7 @@ fn new_crate_similar_name_underscore() { } let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("previously named"), - "{:?}", - json.errors); + "{:?}", json.errors); } #[test] @@ -778,10 +738,7 @@ fn new_krate_git_upload() { let path = ::git::checkout().join("3/f/fgt"); assert!(path.exists()); let mut contents = String::new(); - File::open(&path) - .unwrap() - .read_to_string(&mut contents) - .unwrap(); + File::open(&path).unwrap().read_to_string(&mut contents).unwrap(); let p: git::Crate = json::decode(&contents).unwrap(); assert_eq!(p.name, "fgt"); assert_eq!(p.vers, "1.0.0"); @@ -795,11 +752,9 @@ fn new_krate_git_upload_appends() { let (_b, app, middle) = ::app(); let path = ::git::checkout().join("3/f/fpp"); fs::create_dir_all(path.parent().unwrap()).unwrap(); - File::create(&path) - .unwrap() - .write_all(br#"{"name":"FPP","vers":"0.0.1","deps":[],"features":{},"cksum":"3j3"} -"#) - .unwrap(); + File::create(&path).unwrap().write_all( + br#"{"name":"FPP","vers":"0.0.1","deps":[],"features":{},"cksum":"3j3"} +"#).unwrap(); let mut req = ::new_req(app.clone(), "FPP", "1.0.0"); ::sign_in(&mut req, &app); @@ -807,10 +762,7 @@ fn new_krate_git_upload_appends() { ::json::(&mut response); let mut contents = String::new(); - File::open(&path) - .unwrap() - .read_to_string(&mut contents) - .unwrap(); + File::open(&path).unwrap().read_to_string(&mut contents).unwrap(); let mut lines = contents.lines(); let p1: git::Crate = json::decode(lines.next().unwrap().trim()).unwrap(); let p2: git::Crate = json::decode(lines.next().unwrap().trim()).unwrap(); @@ -833,8 +785,8 @@ fn new_krate_git_upload_with_conflicts() { let sig = repo.signature().unwrap(); let parent = repo.find_commit(target).unwrap(); let tree = repo.find_tree(parent.tree_id()).unwrap(); - repo.commit(Some("HEAD"), &sig, &sig, "empty commit", &tree, &[&parent]) - .unwrap(); + repo.commit(Some("HEAD"), &sig, &sig, "empty commit", &tree, + &[&parent]).unwrap(); } let mut req = ::new_req(app.clone(), "foo_conflicts", "1.0.0"); @@ -859,8 +811,7 @@ fn new_krate_dependency_missing() { ::sign_in(&mut req, &app); let mut response = ok_resp!(middle.call(&mut req)); let json = ::json::<::Bad>(&mut response); - assert!(json.errors[0] - .detail + assert!(json.errors[0].detail .contains("no known crate named `bar_missing`")); } @@ -873,11 +824,9 @@ fn summary_doesnt_die() { #[test] fn download() { - use time::{Duration, now_utc, strftime}; + use ::time::{Duration, now_utc, strftime}; let (_b, app, middle) = ::app(); - let mut req = ::req(app.clone(), - Method::Get, - "/api/v1/crates/foo_download/1.0.0/download"); + let mut req = ::req(app.clone(), Method::Get, "/api/v1/crates/foo_download/1.0.0/download"); { let conn = app.diesel_database.get().unwrap(); let user = ::new_user("foo").create_or_update(&conn).unwrap(); @@ -939,13 +888,12 @@ fn download() { #[test] fn download_bad() { let (_b, app, middle) = ::app(); - let mut req = ::req(app.clone(), - Method::Get, - "/api/v1/crates/foo_bad/0.1.0/download"); + let mut req = ::req(app.clone(), Method::Get, "/api/v1/crates/foo_bad/0.1.0/download"); { let conn = app.diesel_database.get().unwrap(); let user = ::new_user("foo").create_or_update(&conn).unwrap(); - ::CrateBuilder::new("foo_bad", user.id).expect_build(&conn); + ::CrateBuilder::new("foo_bad", user.id) + .expect_build(&conn); } let response = t_resp!(middle.call(&mut req)); assert_eq!(404, response.status.0) @@ -955,15 +903,15 @@ fn download_bad() { fn dependencies() { let (_b, app, middle) = ::app(); - let mut req = ::req(app.clone(), - Method::Get, - "/api/v1/crates/foo_deps/1.0.0/dependencies"); + let mut req = ::req(app.clone(), Method::Get, "/api/v1/crates/foo_deps/1.0.0/dependencies"); { let conn = app.diesel_database.get().unwrap(); let user = ::new_user("foo").create_or_update(&conn).unwrap(); - let c1 = ::CrateBuilder::new("foo_deps", user.id).expect_build(&conn); + let c1 = ::CrateBuilder::new("foo_deps", user.id) + .expect_build(&conn); let v = ::new_version(c1.id, "1.0.0").save(&conn, &[]).unwrap(); - let c2 = ::CrateBuilder::new("bar_deps", user.id).expect_build(&conn); + let c2 = ::CrateBuilder::new("bar_deps", user.id) + .expect_build(&conn); ::new_dependency(&conn, &v, &c2); } @@ -979,9 +927,7 @@ fn dependencies() { #[test] fn diesel_not_found_results_in_404() { let (_b, app, middle) = ::app(); - let mut req = ::req(app.clone(), - Method::Get, - "/api/v1/crates/foo_following/following"); + let mut req = ::req(app.clone(), Method::Get, "/api/v1/crates/foo_following/following"); { let conn = app.diesel_database.get().unwrap(); @@ -995,19 +941,11 @@ fn diesel_not_found_results_in_404() { #[test] fn following() { - #[derive(RustcDecodable)] - struct F { - following: bool, - } - #[derive(RustcDecodable)] - struct O { - ok: bool, - } + #[derive(RustcDecodable)] struct F { following: bool } + #[derive(RustcDecodable)] struct O { ok: bool } let (_b, app, middle) = ::app(); - let mut req = ::req(app.clone(), - Method::Get, - "/api/v1/crates/foo_following/following"); + let mut req = ::req(app.clone(), Method::Get, "/api/v1/crates/foo_following/following"); let user; { @@ -1021,14 +959,14 @@ fn following() { assert!(!::json::(&mut response).following); req.with_path("/api/v1/crates/foo_following/follow") - .with_method(Method::Put); + .with_method(Method::Put); let mut response = ok_resp!(middle.call(&mut req)); assert!(::json::(&mut response).ok); let mut response = ok_resp!(middle.call(&mut req)); assert!(::json::(&mut response).ok); req.with_path("/api/v1/crates/foo_following/following") - .with_method(Method::Get); + .with_method(Method::Get); let mut response = ok_resp!(middle.call(&mut req)); assert!(::json::(&mut response).following); @@ -1040,34 +978,28 @@ fn following() { assert_eq!(l.crates.len(), 1); req.with_path("/api/v1/crates/foo_following/follow") - .with_method(Method::Delete); + .with_method(Method::Delete); let mut response = ok_resp!(middle.call(&mut req)); assert!(::json::(&mut response).ok); let mut response = ok_resp!(middle.call(&mut req)); assert!(::json::(&mut response).ok); req.with_path("/api/v1/crates/foo_following/following") - .with_method(Method::Get); + .with_method(Method::Get); let mut response = ok_resp!(middle.call(&mut req)); assert!(!::json::(&mut response).following); req.with_path("/api/v1/crates") - .with_query("following=1") - .with_method(Method::Get); + .with_query("following=1") + .with_method(Method::Get); let mut response = ok_resp!(middle.call(&mut req)); assert_eq!(::json::(&mut response).crates.len(), 0); } #[test] fn owners() { - #[derive(RustcDecodable)] - struct R { - users: Vec, - } - #[derive(RustcDecodable)] - struct O { - ok: bool, - } + #[derive(RustcDecodable)] struct R { users: Vec } + #[derive(RustcDecodable)] struct O { ok: bool } let (_b, app, middle) = ::app(); let mut req = ::req(app.clone(), Method::Get, "/api/v1/crates/foo_owners/owners"); @@ -1089,7 +1021,7 @@ fn owners() { let body = r#"{"users":["foobar"]}"#; let mut response = ok_resp!(middle.call(req.with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_body(body.as_bytes()))); assert!(::json::(&mut response).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get))); @@ -1098,7 +1030,7 @@ fn owners() { let body = r#"{"users":["foobar"]}"#; let mut response = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_body(body.as_bytes()))); + .with_body(body.as_bytes()))); assert!(::json::(&mut response).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get))); @@ -1107,25 +1039,19 @@ fn owners() { let body = r#"{"users":["foo"]}"#; let mut response = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_body(body.as_bytes()))); + .with_body(body.as_bytes()))); ::json::<::Bad>(&mut response); let body = r#"{"users":["foobar"]}"#; let mut response = ok_resp!(middle.call(req.with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_body(body.as_bytes()))); assert!(::json::(&mut response).ok); } #[test] fn yank() { - #[derive(RustcDecodable)] - struct O { - ok: bool, - } - #[derive(RustcDecodable)] - struct V { - version: EncodableVersion, - } + #[derive(RustcDecodable)] struct O { ok: bool } + #[derive(RustcDecodable)] struct V { version: EncodableVersion } let (_b, app, middle) = ::app(); let path = ::git::checkout().join("3/f/fyk"); @@ -1135,53 +1061,44 @@ fn yank() { let mut response = ok_resp!(middle.call(&mut req)); ::json::(&mut response); let mut contents = String::new(); - File::open(&path) - .unwrap() - .read_to_string(&mut contents) - .unwrap(); + File::open(&path).unwrap().read_to_string(&mut contents).unwrap(); assert!(contents.contains("\"yanked\":false")); // make sure it's not yanked let mut r = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk/1.0.0"))); + .with_path("/api/v1/crates/fyk/1.0.0"))); assert!(!::json::(&mut r).version.yanked); // yank it let mut r = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_path("/api/v1/crates/fyk/1.0.0/yank"))); + .with_path("/api/v1/crates/fyk/1.0.0/yank"))); assert!(::json::(&mut r).ok); let mut contents = String::new(); - File::open(&path) - .unwrap() - .read_to_string(&mut contents) - .unwrap(); + File::open(&path).unwrap().read_to_string(&mut contents).unwrap(); assert!(contents.contains("\"yanked\":true")); let mut r = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk/1.0.0"))); + .with_path("/api/v1/crates/fyk/1.0.0"))); assert!(::json::(&mut r).version.yanked); // un-yank it let mut r = ok_resp!(middle.call(req.with_method(Method::Put) - .with_path("/api/v1/crates/fyk/1.0.0/unyank"))); + .with_path("/api/v1/crates/fyk/1.0.0/unyank"))); assert!(::json::(&mut r).ok); let mut contents = String::new(); - File::open(&path) - .unwrap() - .read_to_string(&mut contents) - .unwrap(); + File::open(&path).unwrap().read_to_string(&mut contents).unwrap(); assert!(contents.contains("\"yanked\":false")); let mut r = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk/1.0.0"))); + .with_path("/api/v1/crates/fyk/1.0.0"))); assert!(!::json::(&mut r).version.yanked); } #[test] fn yank_not_owner() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate(&app, ::new_user("bar"), "foo_not"); + let mut req = ::request_with_user_and_mock_crate( + &app, ::new_user("bar"), "foo_not"); ::sign_in(&mut req, &app); - req.with_method(Method::Delete) - .with_path("/api/v1/crates/foo_not/1.0.0/yank"); + req.with_method(Method::Delete).with_path("/api/v1/crates/foo_not/1.0.0/yank"); let mut response = ok_resp!(middle.call(&mut req)); ::json::<::Bad>(&mut response); } @@ -1206,62 +1123,62 @@ fn yank_max_version() { // add version 2.0.0 let body = ::new_req_body_version_2(::krate("fyk_max")); let mut response = ok_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_method(Method::Put) - .with_body(&body))); + .with_method(Method::Put) + .with_body(&body))); let json: GoodCrate = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); // yank version 1.0.0 let mut r = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_path("/api/v1/crates/fyk_max/1.0.0/yank"))); + .with_path("/api/v1/crates/fyk_max/1.0.0/yank"))); assert!(::json::(&mut r).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + .with_path("/api/v1/crates/fyk_max"))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); // unyank version 1.0.0 let mut r = ok_resp!(middle.call(req.with_method(Method::Put) - .with_path("/api/v1/crates/fyk_max/1.0.0/unyank"))); + .with_path("/api/v1/crates/fyk_max/1.0.0/unyank"))); assert!(::json::(&mut r).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + .with_path("/api/v1/crates/fyk_max"))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); // yank version 2.0.0 let mut r = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_path("/api/v1/crates/fyk_max/2.0.0/yank"))); + .with_path("/api/v1/crates/fyk_max/2.0.0/yank"))); assert!(::json::(&mut r).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + .with_path("/api/v1/crates/fyk_max"))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "1.0.0"); // yank version 1.0.0 let mut r = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_path("/api/v1/crates/fyk_max/1.0.0/yank"))); + .with_path("/api/v1/crates/fyk_max/1.0.0/yank"))); assert!(::json::(&mut r).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + .with_path("/api/v1/crates/fyk_max"))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "0.0.0"); // unyank version 2.0.0 let mut r = ok_resp!(middle.call(req.with_method(Method::Put) - .with_path("/api/v1/crates/fyk_max/2.0.0/unyank"))); + .with_path("/api/v1/crates/fyk_max/2.0.0/unyank"))); assert!(::json::(&mut r).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + .with_path("/api/v1/crates/fyk_max"))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); // unyank version 1.0.0 let mut r = ok_resp!(middle.call(req.with_method(Method::Put) - .with_path("/api/v1/crates/fyk_max/1.0.0/unyank"))); + .with_path("/api/v1/crates/fyk_max/1.0.0/unyank"))); assert!(::json::(&mut r).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + .with_path("/api/v1/crates/fyk_max"))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); } @@ -1285,27 +1202,27 @@ fn publish_after_yank_max_version() { // yank version 1.0.0 let mut r = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_path("/api/v1/crates/fyk_max/1.0.0/yank"))); + .with_path("/api/v1/crates/fyk_max/1.0.0/yank"))); assert!(::json::(&mut r).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + .with_path("/api/v1/crates/fyk_max"))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "0.0.0"); // add version 2.0.0 let body = ::new_req_body_version_2(::krate("fyk_max")); let mut response = ok_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_method(Method::Put) - .with_body(&body))); + .with_method(Method::Put) + .with_body(&body))); let json: GoodCrate = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); // unyank version 1.0.0 let mut r = ok_resp!(middle.call(req.with_method(Method::Put) - .with_path("/api/v1/crates/fyk_max/1.0.0/unyank"))); + .with_path("/api/v1/crates/fyk_max/1.0.0/unyank"))); assert!(::json::(&mut r).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + .with_path("/api/v1/crates/fyk_max"))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); } @@ -1356,9 +1273,7 @@ fn good_categories() { ::sign_in(&mut req, &app); { let conn = app.diesel_database.get().unwrap(); - ::new_category("Category 1", "cat1") - .find_or_create(&conn) - .unwrap(); + ::new_category("Category 1", "cat1").find_or_create(&conn).unwrap(); } let mut response = ok_resp!(middle.call(&mut req)); let json: GoodCrate = ::json(&mut response); @@ -1386,8 +1301,10 @@ fn good_badges() { let krate = ::krate("foobadger"); let mut badges = HashMap::new(); let mut badge_attributes = HashMap::new(); - badge_attributes.insert(String::from("repository"), - String::from("rust-lang/crates.io")); + badge_attributes.insert( + String::from("repository"), + String::from("rust-lang/crates.io") + ); badges.insert(String::from("travis-ci"), badge_attributes); let (_b, app, middle) = ::app(); @@ -1399,16 +1316,19 @@ fn good_badges() { assert_eq!(json.krate.name, "foobadger"); assert_eq!(json.krate.max_version, "1.0.0"); - let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/foobadger"))); + let mut response = ok_resp!( + middle.call(req.with_method(Method::Get) + .with_path("/api/v1/crates/foobadger"))); let json: CrateResponse = ::json(&mut response); let badges = json.krate.badges.unwrap(); assert_eq!(badges.len(), 1); assert_eq!(badges[0].badge_type, "travis-ci"); - assert_eq!(badges[0].attributes.get("repository").unwrap(), - &Some(String::from("rust-lang/crates.io"))); + assert_eq!( + badges[0].attributes.get("repository").unwrap(), + &Some(String::from("rust-lang/crates.io")) + ); } #[test] @@ -1418,12 +1338,18 @@ fn ignored_badges() { // Known badge type, missing required repository attribute let mut badge_attributes = HashMap::new(); - badge_attributes.insert(String::from("branch"), String::from("master")); + badge_attributes.insert( + String::from("branch"), + String::from("master") + ); badges.insert(String::from("travis-ci"), badge_attributes); // Unknown badge type let mut unknown_badge_attributes = HashMap::new(); - unknown_badge_attributes.insert(String::from("repository"), String::from("rust-lang/rust")); + unknown_badge_attributes.insert( + String::from("repository"), + String::from("rust-lang/rust") + ); badges.insert(String::from("not-a-badge"), unknown_badge_attributes); let (_b, app, middle) = ::app(); @@ -1436,15 +1362,12 @@ fn ignored_badges() { assert_eq!(json.krate.name, "foo_ignored_badge"); assert_eq!(json.krate.max_version, "1.0.0"); assert_eq!(json.warnings.invalid_badges.len(), 2); - assert!(json.warnings - .invalid_badges - .contains(&"travis-ci".to_string())); - assert!(json.warnings - .invalid_badges - .contains(&"not-a-badge".to_string())); + assert!(json.warnings.invalid_badges.contains(&"travis-ci".to_string())); + assert!(json.warnings.invalid_badges.contains(&"not-a-badge".to_string())); - let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/foo_ignored_badge",))); + let mut response = ok_resp!( + middle.call(req.with_method(Method::Get) + .with_path("/api/v1/crates/foo_ignored_badge"))); let json: CrateResponse = ::json(&mut response); @@ -1458,7 +1381,8 @@ fn reverse_dependencies() { let v100 = semver::Version::parse("1.0.0").unwrap(); let v110 = semver::Version::parse("1.1.0").unwrap(); - let mut req = ::req(app, Method::Get, "/api/v1/crates/c1/reverse_dependencies"); + let mut req = ::req(app, Method::Get, + "/api/v1/crates/c1/reverse_dependencies"); ::mock_user(&mut req, ::user("foo")); let (c1, _) = ::mock_crate_vers(&mut req, ::krate("c1"), &v100); let (_, c2v1) = ::mock_crate_vers(&mut req, ::krate("c2"), &v100); @@ -1489,7 +1413,8 @@ fn reverse_dependencies_when_old_version_doesnt_depend_but_new_does() { let v100 = semver::Version::parse("1.0.0").unwrap(); let v110 = semver::Version::parse("1.1.0").unwrap(); let v200 = semver::Version::parse("2.0.0").unwrap(); - let mut req = ::req(app, Method::Get, "/api/v1/crates/c1/reverse_dependencies"); + let mut req = ::req(app, Method::Get, + "/api/v1/crates/c1/reverse_dependencies"); ::mock_user(&mut req, ::user("foo")); let (c1, _) = ::mock_crate_vers(&mut req, ::krate("c1"), &v110); let _ = ::mock_crate_vers(&mut req, ::krate("c2"), &v100); @@ -1510,7 +1435,8 @@ fn reverse_dependencies_when_old_version_depended_but_new_doesnt() { let v100 = semver::Version::parse("1.0.0").unwrap(); let v200 = semver::Version::parse("2.0.0").unwrap(); - let mut req = ::req(app, Method::Get, "/api/v1/crates/c1/reverse_dependencies"); + let mut req = ::req(app, Method::Get, + "/api/v1/crates/c1/reverse_dependencies"); ::mock_user(&mut req, ::user("foo")); let (c1, _) = ::mock_crate_vers(&mut req, ::krate("c1"), &v100); let (_, c2v1) = ::mock_crate_vers(&mut req, ::krate("c2"), &v100); @@ -1530,7 +1456,8 @@ fn prerelease_versions_not_included_in_reverse_dependencies() { let v100 = semver::Version::parse("1.0.0").unwrap(); let v110_pre = semver::Version::parse("1.1.0-pre").unwrap(); - let mut req = ::req(app, Method::Get, "/api/v1/crates/c1/reverse_dependencies"); + let mut req = ::req(app, Method::Get, + "/api/v1/crates/c1/reverse_dependencies"); ::mock_user(&mut req, ::user("foo")); let (c1, _) = ::mock_crate_vers(&mut req, ::krate("c1"), &v100); let _ = ::mock_crate_vers(&mut req, ::krate("c2"), &v110_pre); @@ -1552,7 +1479,8 @@ fn yanked_versions_not_included_in_reverse_dependencies() { let v100 = semver::Version::parse("1.0.0").unwrap(); let v200 = semver::Version::parse("2.0.0").unwrap(); - let mut req = ::req(app, Method::Get, "/api/v1/crates/c1/reverse_dependencies"); + let mut req = ::req(app, Method::Get, + "/api/v1/crates/c1/reverse_dependencies"); ::mock_user(&mut req, ::user("foo")); let (c1, _) = ::mock_crate_vers(&mut req, ::krate("c1"), &v100); let _ = ::mock_crate_vers(&mut req, ::krate("c2"), &v100); @@ -1589,8 +1517,7 @@ fn author_license_and_description_required() { assert!(json.errors[0].detail.contains("author") && json.errors[0].detail.contains("description") && json.errors[0].detail.contains("license"), - "{:?}", - json.errors); + "{:?}", json.errors); new_crate.license = Some("MIT".to_string()); new_crate.authors.push("".to_string()); @@ -1599,8 +1526,7 @@ fn author_license_and_description_required() { assert!(json.errors[0].detail.contains("author") && json.errors[0].detail.contains("description") && !json.errors[0].detail.contains("license"), - "{:?}", - json.errors); + "{:?}", json.errors); new_crate.license = None; new_crate.license_file = Some("foo".to_string()); @@ -1610,6 +1536,6 @@ fn author_license_and_description_required() { assert!(!json.errors[0].detail.contains("author") && json.errors[0].detail.contains("description") && !json.errors[0].detail.contains("license"), - "{:?}", - json.errors); + "{:?}", json.errors); } + diff --git a/src/tests/record.rs b/src/tests/record.rs index cfe0d323867..2a29ee01614 100644 --- a/src/tests/record.rs +++ b/src/tests/record.rs @@ -37,9 +37,7 @@ impl Write for Sink { fn write(&mut self, data: &[u8]) -> io::Result { Write::write(&mut *self.0.lock().unwrap(), data) } - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } + fn flush(&mut self) -> io::Result<()> { Ok(()) } } impl Drop for Bomb { @@ -47,11 +45,12 @@ impl Drop for Bomb { t!(self.quit.send(())); drop(TcpStream::connect(&t!(self.accept.local_addr()))); let res = self.rx.recv(); - let stderr = str::from_utf8(&self.iorx.0.lock().unwrap()) - .unwrap() - .to_string(); + let stderr = str::from_utf8(&self.iorx.0.lock().unwrap()).unwrap() + .to_string(); match res { - Err(..) if !thread::panicking() => panic!("server subtask failed: {}", stderr), + Err(..) if !thread::panicking() => { + panic!("server subtask failed: {}", stderr) + } _ => { if stderr.len() > 0 { println!("server subtask failed: {}", stderr) @@ -62,11 +61,7 @@ impl Drop for Bomb { } fn cache_file(name: &str) -> PathBuf { - PathBuf::from(file!()) - .parent() - .unwrap() - .join("http-data") - .join(name) + PathBuf::from(file!()).parent().unwrap().join("http-data").join(name) } pub fn proxy() -> (String, Bomb) { @@ -86,20 +81,18 @@ pub fn proxy() -> (String, Bomb) { let (quittx, quitrx) = channel(); - thread::spawn(move || { + thread::spawn(move|| { let mut file = None; for socket in a.incoming() { - if quitrx.try_recv().is_ok() { - break; - } + if quitrx.try_recv().is_ok() { break } let socket = t!(socket); if file.is_none() { let io = t!(if record { - File::create(&data) - } else { - File::open(&data) - }); + File::create(&data) + } else { + File::open(&data) + }); file = Some(BufStream::new(io)); } @@ -119,13 +112,7 @@ pub fn proxy() -> (String, Bomb) { tx.send(()).unwrap(); }); - (ret, - Bomb { - accept: a2, - rx: rx, - iorx: Sink(sink), - quit: quittx, - }) + (ret, Bomb { accept: a2, rx: rx, iorx: Sink(sink), quit: quittx }) } fn record_http(mut socket: TcpStream, data: &mut BufStream) { @@ -137,8 +124,7 @@ fn record_http(mut socket: TcpStream, data: &mut BufStream) { respond(handle, headers, body, &mut response); t!(socket.write_all(&response)); - t!(write!(data, - "===REQUEST {}\n{}\n===RESPONSE {}\n{}\n", + t!(write!(data, "===REQUEST {}\n{}\n===RESPONSE {}\n{}\n", request.len(), str::from_utf8(&request).unwrap(), response.len(), @@ -159,7 +145,7 @@ fn record_http(mut socket: TcpStream, data: &mut BufStream) { for line in lines { let line = t!(line); if line.len() < 3 { - break; + break } t!(headers.append(&line)); } @@ -180,14 +166,16 @@ fn record_http(mut socket: TcpStream, data: &mut BufStream) { { let mut transfer = handle.transfer(); t!(transfer.header_function(|header| { - headers.push(header.to_owned()); - true - })); + headers.push(header.to_owned()); + true + })); t!(transfer.write_function(|data| { - response.extend(data); - Ok(data.len()) - })); - t!(transfer.read_function(|buf| socket.read(buf).map_err(|_| ReadError::Abort))); + response.extend(data); + Ok(data.len()) + })); + t!(transfer.read_function(|buf| { + socket.read(buf).map_err(|_| ReadError::Abort) + })); t!(transfer.perform()); } @@ -195,11 +183,15 @@ fn record_http(mut socket: TcpStream, data: &mut BufStream) { (handle, headers, response) } - fn respond(mut handle: Easy, headers: Vec>, body: Vec, mut socket: W) { - t!(socket.write_all(format!("HTTP/1.1 {}\r\n", t!(handle.response_code())).as_bytes())); + fn respond(mut handle: Easy, + headers: Vec>, + body: Vec, + mut socket: W) { + t!(socket.write_all(format!("HTTP/1.1 {}\r\n", + t!(handle.response_code())).as_bytes())); for header in headers { if header.starts_with(b"Transfer-Encoding: ") { - continue; + continue } t!(socket.write_all(&header)); t!(socket.write_all(b"\r\n")); @@ -209,7 +201,8 @@ fn record_http(mut socket: TcpStream, data: &mut BufStream) { } } -fn replay_http(socket: TcpStream, data: &mut BufStream, stdout: &mut Write) { +fn replay_http(socket: TcpStream, data: &mut BufStream, + stdout: &mut Write) { let mut writer = socket.try_clone().unwrap(); let socket = BufReader::new(socket); @@ -225,35 +218,22 @@ fn replay_http(socket: TcpStream, data: &mut BufStream, stdout: &mut Write let mut actual_lines = socket.lines().map(|s| s.unwrap()); // validate the headers - let mut expected: HashSet = expected_lines - .by_ref() - .take_while(|l| l.len() > 2) - .collect(); + let mut expected: HashSet = expected_lines.by_ref() + .take_while(|l| l.len() > 2) + .collect(); let mut found = HashSet::new(); t!(writeln!(stdout, "expecting: {:?}", expected)); for line in actual_lines.by_ref().take_while(|l| l.len() > 2) { t!(writeln!(stdout, "received: {}", line.trim())); - if !found.insert(line.clone()) { - continue; - } - if expected.remove(&line) { - continue; - } - if line.starts_with("Date:") { - continue; - } - if line.starts_with("Authorization:") { - continue; - } + if !found.insert(line.clone()) { continue } + if expected.remove(&line) { continue } + if line.starts_with("Date:") { continue } + if line.starts_with("Authorization:") { continue } panic!("unexpected header: {}", line); } for line in expected.iter() { - if line.starts_with("Date:") { - continue; - } - if line.starts_with("Authorization:") { - continue; - } + if line.starts_with("Date:") { continue } + if line.starts_with("Authorization:") { continue } panic!("didn't receive header: {}", line); } @@ -267,11 +247,10 @@ fn replay_http(socket: TcpStream, data: &mut BufStream, stdout: &mut Write let response_size = response.next().unwrap().trim().parse().unwrap(); let mut response = Vec::new(); data.take(response_size).read_to_end(&mut response).unwrap(); - let lines = <[_]>::split(&response[..], |b| *b == b'\n').map(|s| str::from_utf8(s).unwrap()); + let lines = <[_]>::split(&response[..], |b| *b == b'\n') + .map(|s| str::from_utf8(s).unwrap()); for line in lines { - if line.starts_with("Date:") { - continue; - } + if line.starts_with("Date:") { continue } writer.write_all(line.as_bytes()).unwrap(); writer.write_all(b"\r\n").unwrap(); } @@ -283,28 +262,22 @@ impl GhUser { self.init.call_once(|| self.init()); let mut u = ::new_user(self.login); u.gh_access_token = Cow::Owned(self.token()); - return u; + return u } - fn filename(&self) -> PathBuf { - cache_file(&format!("gh-{}", self.login)) - } + fn filename(&self) -> PathBuf { cache_file(&format!("gh-{}", self.login)) } fn token(&self) -> String { let mut token = String::new(); - File::open(&self.filename()) - .unwrap() - .read_to_string(&mut token) - .unwrap(); - return token; + File::open(&self.filename()).unwrap().read_to_string(&mut token).unwrap(); + return token } fn init(&self) { - if fs::metadata(&self.filename()).is_ok() { - return; - } + if fs::metadata(&self.filename()).is_ok() { return } - let password = ::env(&format!("GH_PASS_{}", self.login.replace("-", "_"))); + let password = ::env(&format!("GH_PASS_{}", + self.login.replace("-", "_"))); #[derive(RustcEncodable)] struct Authorization { scopes: Vec, @@ -314,15 +287,13 @@ impl GhUser { } let mut handle = Easy::new(); let url = format!("https://{}:{}@api.github.com/authorizations", - self.login, - password); + self.login, password); let body = json::encode(&Authorization { - scopes: vec!["read:org".to_string()], - note: "crates.io test".to_string(), - client_id: ::env("GH_CLIENT_ID"), - client_secret: ::env("GH_CLIENT_SECRET"), - }) - .unwrap(); + scopes: vec!["read:org".to_string()], + note: "crates.io test".to_string(), + client_id: ::env("GH_CLIENT_ID"), + client_secret: ::env("GH_CLIENT_SECRET"), + }).unwrap(); t!(handle.url(&url)); t!(handle.post(true)); @@ -335,26 +306,26 @@ impl GhUser { let mut response = Vec::new(); { let mut transfer = handle.transfer(); - t!(transfer.read_function(|buf| body.read(buf).map_err(|_| ReadError::Abort))); + t!(transfer.read_function(|buf| { + body.read(buf).map_err(|_| ReadError::Abort) + })); t!(transfer.write_function(|data| { - response.extend(data); - Ok(data.len()) - })); + response.extend(data); + Ok(data.len()) + })); t!(transfer.perform()) } if t!(handle.response_code()) < 200 || t!(handle.response_code()) >= 300 { - panic!("failed to get a 200 {}", String::from_utf8_lossy(&response)); + panic!("failed to get a 200 {}", + String::from_utf8_lossy(&response)); } #[derive(RustcDecodable)] - struct Response { - token: String, - } - let resp: Response = json::decode(str::from_utf8(&response).unwrap()).unwrap(); - File::create(&self.filename()) - .unwrap() - .write_all(&resp.token.as_bytes()) - .unwrap(); + struct Response { token: String } + let resp: Response = json::decode(str::from_utf8(&response) + .unwrap()).unwrap(); + File::create(&self.filename()).unwrap() + .write_all(&resp.token.as_bytes()).unwrap(); } } diff --git a/src/tests/team.rs b/src/tests/team.rs index d8ddaefd29f..52ff6f5d135 100644 --- a/src/tests/team.rs +++ b/src/tests/team.rs @@ -9,21 +9,11 @@ use record::GhUser; // Teams: `crates-test-org:owners`, `crates-test-org:just-for-crates-2` // tester-1 is on owners only, tester-2 is on both -static GH_USER_1: GhUser = GhUser { - login: "crates-tester-1", - init: ONCE_INIT, -}; -static GH_USER_2: GhUser = GhUser { - login: "crates-tester-2", - init: ONCE_INIT, -}; - -fn mock_user_on_only_x() -> NewUser<'static> { - GH_USER_1.user() -} -fn mock_user_on_x_and_y() -> NewUser<'static> { - GH_USER_2.user() -} +static GH_USER_1: GhUser = GhUser { login: "crates-tester-1", init: ONCE_INIT }; +static GH_USER_2: GhUser = GhUser { login: "crates-tester-2", init: ONCE_INIT }; + +fn mock_user_on_only_x() -> NewUser<'static> { GH_USER_1.user() } +fn mock_user_on_x_and_y() -> NewUser<'static> { GH_USER_2.user() } fn body_for_team_y() -> &'static str { r#"{"users":["github:crates-test-org:just-for-crates-2"]}"# @@ -37,111 +27,103 @@ fn body_for_team_x() -> &'static str { #[test] fn not_github() { let (_b, app, middle) = ::app(); - let mut req = - ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_not_github"); + let mut req = ::request_with_user_and_mock_crate( + &app, mock_user_on_x_and_y(), "foo_not_github"); let body = r#"{"users":["dropbox:foo:foo"]}"#; let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_not_github/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); assert!(json.errors[0].detail.contains("unknown organization"), - "{:?}", - json.errors); + "{:?}", json.errors); } #[test] fn weird_name() { let (_b, app, middle) = ::app(); - let mut req = - ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_weird_name"); + let mut req = ::request_with_user_and_mock_crate( + &app, mock_user_on_x_and_y(), "foo_weird_name"); let body = r#"{"users":["github:foo/../bar:wut"]}"#; let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_weird_name/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); - assert!(json.errors[0] - .detail - .contains("organization cannot contain"), - "{:?}", - json.errors); + .with_method(Method::Put) + .with_body(body.as_bytes()))); + assert!(json.errors[0].detail.contains("organization cannot contain"), + "{:?}", json.errors); } // Test adding team without second `:` #[test] fn one_colon() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_one_colon"); + let mut req = ::request_with_user_and_mock_crate( + &app, mock_user_on_x_and_y(), "foo_one_colon"); let body = r#"{"users":["github:foo"]}"#; let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_one_colon/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); assert!(json.errors[0].detail.contains("missing github team"), - "{:?}", - json.errors); + "{:?}", json.errors); } #[test] fn nonexistent_team() { let (_b, app, middle) = ::app(); - let mut req = - ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_nonexistent"); + let mut req = ::request_with_user_and_mock_crate( + &app, mock_user_on_x_and_y(), "foo_nonexistent"); let body = r#"{"users":["github:crates-test-org:this-does-not-exist"]}"#; let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_nonexistent/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); - assert!(json.errors[0] - .detail - .contains("could not find the github team"), - "{:?}", - json.errors); + .with_method(Method::Put) + .with_body(body.as_bytes()))); + assert!(json.errors[0].detail.contains("could not find the github team"), + "{:?}", json.errors); } // Test adding team as owner when on it #[test] fn add_team_as_member() { let (_b, app, middle) = ::app(); - let mut req = - ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_team_member"); + let mut req = ::request_with_user_and_mock_crate( + &app, mock_user_on_x_and_y(), "foo_team_member"); let body = body_for_team_x(); ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_team_member/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); } // Test adding team as owner when not on in #[test] fn add_team_as_non_member() { let (_b, app, middle) = ::app(); - let mut req = - ::request_with_user_and_mock_crate(&app, mock_user_on_only_x(), "foo_team_non_member"); + let mut req = ::request_with_user_and_mock_crate( + &app, mock_user_on_only_x(), "foo_team_non_member"); let body = body_for_team_y(); let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_team_non_member/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); assert!(json.errors[0].detail.contains("only members"), - "{:?}", - json.errors); + "{:?}", json.errors); } #[test] fn remove_team_as_named_owner() { let (_b, app, middle) = ::app(); - let mut req = - ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_remove_team"); + let mut req = ::request_with_user_and_mock_crate( + &app, mock_user_on_x_and_y(), "foo_remove_team"); let body = body_for_team_x(); ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_remove_team/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); let body = body_for_team_x(); ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_remove_team/owners") - .with_method(Method::Delete) - .with_body(body.as_bytes()))); + .with_method(Method::Delete) + .with_body(body.as_bytes()))); { let conn = app.diesel_database.get().unwrap(); @@ -150,23 +132,22 @@ fn remove_team_as_named_owner() { } let body = ::new_req_body_version_2(::krate("foo_remove_team")); let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_body(&body) - .with_method(Method::Put))); + .with_body(&body) + .with_method(Method::Put))); assert!(json.errors[0].detail.contains("another user"), - "{:?}", - json.errors); + "{:?}", json.errors); } #[test] fn remove_team_as_team_owner() { let (_b, app, middle) = ::app(); - let mut req = - ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_remove_team_owner"); + let mut req = ::request_with_user_and_mock_crate( + &app, mock_user_on_x_and_y(), "foo_remove_team_owner"); let body = body_for_team_x(); ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_remove_team_owner/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); { let conn = app.diesel_database.get().unwrap(); @@ -175,17 +156,16 @@ fn remove_team_as_team_owner() { } let body = body_for_team_x(); let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_remove_team_owner/owners") - .with_method(Method::Delete) - .with_body(body.as_bytes()))); + .with_method(Method::Delete) + .with_body(body.as_bytes()))); assert!(json.errors[0].detail.contains("don't have permission"), - "{:?}", - json.errors); + "{:?}", json.errors); let body = ::new_req_body_version_2(::krate("foo_remove_team_owner")); ok_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_body(&body) - .with_method(Method::Put))); + .with_body(&body) + .with_method(Method::Put))); } // Test trying to publish a krate we don't own @@ -193,12 +173,13 @@ fn remove_team_as_team_owner() { fn publish_not_owned() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_not_owned"); + let mut req = ::request_with_user_and_mock_crate( + &app, mock_user_on_x_and_y(), "foo_not_owned"); let body = body_for_team_y(); ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_not_owned/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); { let conn = app.diesel_database.get().unwrap(); @@ -207,24 +188,23 @@ fn publish_not_owned() { } let body = ::new_req_body_version_2(::krate("foo_not_owned")); let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_body(&body) - .with_method(Method::Put))); + .with_body(&body) + .with_method(Method::Put))); assert!(json.errors[0].detail.contains("another user"), - "{:?}", - json.errors); + "{:?}", json.errors); } // Test trying to publish a krate we do own (but only because of teams) #[test] fn publish_owned() { let (_b, app, middle) = ::app(); - let mut req = - ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_team_owned"); + let mut req = ::request_with_user_and_mock_crate( + &app, mock_user_on_x_and_y(), "foo_team_owned"); let body = body_for_team_x(); ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_team_owned/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); { let conn = app.diesel_database.get().unwrap(); @@ -233,31 +213,31 @@ fn publish_owned() { } let body = ::new_req_body_version_2(::krate("foo_team_owned")); ok_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_body(&body) - .with_method(Method::Put))); + .with_body(&body) + .with_method(Method::Put))); } // Test trying to change owners (when only on an owning team) #[test] fn add_owners_as_team_owner() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_add_owner"); + let mut req = ::request_with_user_and_mock_crate( + &app, mock_user_on_x_and_y(), "foo_add_owner"); let body = body_for_team_x(); ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_add_owner/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); { let conn = app.diesel_database.get().unwrap(); let user = mock_user_on_only_x().create_or_update(&conn).unwrap(); ::sign_in_as(&mut req, &user); } - let body = r#"{"users":["FlashCat"]}"#; // User doesn't matter + let body = r#"{"users":["FlashCat"]}"#; // User doesn't matter let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_add_owner/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); assert!(json.errors[0].detail.contains("don't have permission"), - "{:?}", - json.errors); + "{:?}", json.errors); } diff --git a/src/tests/user.rs b/src/tests/user.rs index 04453488299..2372eec8c34 100644 --- a/src/tests/user.rs +++ b/src/tests/user.rs @@ -7,19 +7,11 @@ use cargo_registry::user::{User, NewUser, EncodableUser}; use cargo_registry::version::EncodableVersion; #[derive(RustcDecodable)] -struct AuthResponse { - url: String, - state: String, -} +struct AuthResponse { url: String, state: String } #[derive(RustcDecodable)] -struct MeResponse { - user: EncodableUser, - api_token: String, -} +struct MeResponse { user: EncodableUser, api_token: String } #[derive(RustcDecodable)] -struct UserShowResponse { - user: EncodableUser, -} +struct UserShowResponse { user: EncodableUser } #[test] fn auth_gives_a_token() { @@ -49,14 +41,16 @@ fn user_insert() { assert_eq!(t!(User::find_by_api_token(&tx, &user.api_token)), user); assert_eq!(t!(User::find(&tx, user.id)), user); - assert_eq!(t!(User::find_or_insert(&tx, 1, "foo", None, None, None, "bar")), - user); - let user2 = t!(User::find_or_insert(&tx, 1, "foo", None, None, None, "baz")); + assert_eq!(t!(User::find_or_insert(&tx, 1, "foo", None, None, None, + "bar")), user); + let user2 = t!(User::find_or_insert(&tx, 1, "foo", None, None, None, + "baz")); assert!(user != user2); assert_eq!(user.id, user2.id); assert_eq!(user2.gh_access_token, "baz"); - let user3 = t!(User::find_or_insert(&tx, 1, "bar", None, None, None, "baz")); + let user3 = t!(User::find_or_insert(&tx, 1, "bar", None, None, None, + "baz")); assert!(user != user3); assert_eq!(user.id, user3.id); assert_eq!(user3.gh_login, "bar"); @@ -103,7 +97,8 @@ fn show() { fn reset_token() { let (_b, app, middle) = ::app(); let mut req = ::req(app, Method::Put, "/me/reset_token"); - let user = User::find_or_insert(req.tx().unwrap(), 1, "foo", None, None, None, "bar").unwrap(); + let user = User::find_or_insert(req.tx().unwrap(), 1, "foo", None, + None, None, "bar").unwrap(); ::sign_in_as(&mut req, &user); ok_resp!(middle.call(&mut req)); @@ -117,8 +112,11 @@ fn crates_by_user_id() { let u; { let conn = app.diesel_database.get().unwrap(); - u = ::new_user("foo").create_or_update(&conn).unwrap(); - ::CrateBuilder::new("foo_my_packages", u.id).expect_build(&conn); + u = ::new_user("foo") + .create_or_update(&conn) + .unwrap(); + ::CrateBuilder::new("foo_my_packages", u.id) + .expect_build(&conn); } let mut req = ::req(app, Method::Get, "/api/v1/crates"); @@ -126,9 +124,7 @@ fn crates_by_user_id() { let mut response = ok_resp!(middle.call(&mut req)); #[derive(RustcDecodable)] - struct Response { - crates: Vec, - } + struct Response { crates: Vec } let response: Response = ::json(&mut response); assert_eq!(response.crates.len(), 1); } @@ -140,10 +136,7 @@ fn following() { versions: Vec, meta: Meta, } - #[derive(RustcDecodable)] - struct Meta { - more: bool, - } + #[derive(RustcDecodable)] struct Meta { more: bool } let (_b, app, middle) = ::app(); let mut req = ::req(app.clone(), Method::Get, "/"); @@ -161,33 +154,35 @@ fn following() { .expect_build(&conn); } - let mut response = ok_resp!(middle.call(req.with_path("/me/updates").with_method(Method::Get))); + let mut response = ok_resp!(middle.call(req.with_path("/me/updates") + .with_method(Method::Get))); let r = ::json::(&mut response); assert_eq!(r.versions.len(), 0); assert_eq!(r.meta.more, false); ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_fighters/follow") - .with_method(Method::Put))); + .with_method(Method::Put))); ok_resp!(middle.call(req.with_path("/api/v1/crates/bar_fighters/follow") - .with_method(Method::Put))); + .with_method(Method::Put))); - let mut response = ok_resp!(middle.call(req.with_path("/me/updates").with_method(Method::Get))); + let mut response = ok_resp!(middle.call(req.with_path("/me/updates") + .with_method(Method::Get))); let r = ::json::(&mut response); assert_eq!(r.versions.len(), 2); assert_eq!(r.meta.more, false); let mut response = ok_resp!(middle.call(req.with_path("/me/updates") - .with_method(Method::Get) - .with_query("per_page=1"))); + .with_method(Method::Get) + .with_query("per_page=1"))); let r = ::json::(&mut response); assert_eq!(r.versions.len(), 1); assert_eq!(r.meta.more, true); ok_resp!(middle.call(req.with_path("/api/v1/crates/bar_fighters/follow") - .with_method(Method::Delete))); + .with_method(Method::Delete))); let mut response = ok_resp!(middle.call(req.with_path("/me/updates") - .with_method(Method::Get) - .with_query("page=2&per_page=1"))); + .with_method(Method::Get) + .with_query("page=2&per_page=1"))); let r = ::json::(&mut response); assert_eq!(r.versions.len(), 0); assert_eq!(r.meta.more, false); diff --git a/src/tests/version.rs b/src/tests/version.rs index db8851d1447..00501ed7449 100644 --- a/src/tests/version.rs +++ b/src/tests/version.rs @@ -8,13 +8,9 @@ use cargo_registry::db::RequestTransaction; use cargo_registry::version::{EncodableVersion, Version}; #[derive(RustcDecodable)] -struct VersionList { - versions: Vec, -} +struct VersionList { versions: Vec } #[derive(RustcDecodable)] -struct VersionResponse { - version: EncodableVersion, -} +struct VersionResponse { version: EncodableVersion } fn sv(s: &str) -> semver::Version { semver::Version::parse(s).unwrap() @@ -50,7 +46,8 @@ fn show() { let v = { let conn = app.diesel_database.get().unwrap(); let user = ::new_user("foo").create_or_update(&conn).unwrap(); - let krate = ::CrateBuilder::new("foo_vers_show", user.id).expect_build(&conn); + let krate = ::CrateBuilder::new("foo_vers_show", user.id) + .expect_build(&conn); ::new_version(krate.id, "2.0.0").save(&conn, &[]).unwrap() }; req.with_path(&format!("/api/v1/versions/{}", v.id)); diff --git a/src/upload.rs b/src/upload.rs index e9f8ff2e15b..7c64b456bf2 100644 --- a/src/upload.rs +++ b/src/upload.rs @@ -55,14 +55,14 @@ impl Decodable for CrateName { return Err(d.error(&format!("invalid crate name specified: {}. \ Valid crate names must start with a letter; contain only \ letters, numbers, hyphens, or underscores; and have {} or \ - fewer characters.", s, MAX_NAME_LENGTH))); + fewer characters.", s, MAX_NAME_LENGTH))) } Ok(CrateName(s)) } } -impl PartialEq for CrateName - where String: PartialEq +impl PartialEq for CrateName where + String: PartialEq, { fn eq(&self, rhs: &T) -> bool { self.0 == *rhs @@ -73,7 +73,7 @@ impl Decodable for Keyword { fn decode(d: &mut D) -> Result { let s = d.read_str()?; if !CrateKeyword::valid_name(&s) { - return Err(d.error(&format!("invalid keyword specified: {}", s))); + return Err(d.error(&format!("invalid keyword specified: {}", s))) } Ok(Keyword(s)) } @@ -89,7 +89,7 @@ impl Decodable for Feature { fn decode(d: &mut D) -> Result { let s = d.read_str()?; if !Crate::valid_feature_name(&s) { - return Err(d.error(&format!("invalid feature name specified: {}", s))); + return Err(d.error(&format!("invalid feature name specified: {}", s))) } Ok(Feature(s)) } @@ -115,8 +115,8 @@ impl Decodable for CrateVersionReq { } } -impl PartialEq for CrateVersionReq - where semver::VersionReq: PartialEq +impl PartialEq for CrateVersionReq where + semver::VersionReq: PartialEq, { fn eq(&self, rhs: &T) -> bool { self.0 == *rhs @@ -127,12 +127,12 @@ impl Decodable for KeywordList { fn decode(d: &mut D) -> Result { let inner: Vec = Decodable::decode(d)?; if inner.len() > 5 { - return Err(d.error("a maximum of 5 keywords per crate are allowed")); + return Err(d.error("a maximum of 5 keywords per crate are allowed")) } for val in &inner { if val.len() > 20 { return Err(d.error("keywords must contain less than 20 \ - characters")); + characters")) } } Ok(KeywordList(inner)) @@ -143,7 +143,7 @@ impl Decodable for CategoryList { fn decode(d: &mut D) -> Result { let inner: Vec = Decodable::decode(d)?; if inner.len() > 5 { - return Err(d.error("a maximum of 5 categories per crate are allowed")); + return Err(d.error("a maximum of 5 categories per crate are allowed")) } Ok(CategoryList(inner)) } @@ -156,10 +156,8 @@ impl Decodable for DependencyKind { "dev" => Ok(DependencyKind::Dev), "build" => Ok(DependencyKind::Build), "normal" => Ok(DependencyKind::Normal), - s => { - Err(d.error(&format!("invalid dependency kind `{}`, must be \ - one of dev, build, or normal", s))) - } + s => Err(d.error(&format!("invalid dependency kind `{}`, must be \ + one of dev, build, or normal", s))), } } } @@ -226,56 +224,40 @@ impl Encodable for DependencyKind { impl Deref for CrateName { type Target = str; - fn deref(&self) -> &str { - &self.0 - } + fn deref(&self) -> &str { &self.0 } } impl Deref for Keyword { type Target = str; - fn deref(&self) -> &str { - &self.0 - } + fn deref(&self) -> &str { &self.0 } } impl Deref for Category { type Target = str; - fn deref(&self) -> &str { - &self.0 - } + fn deref(&self) -> &str { &self.0 } } impl Deref for Feature { type Target = str; - fn deref(&self) -> &str { - &self.0 - } + fn deref(&self) -> &str { &self.0 } } impl Deref for CrateVersion { type Target = semver::Version; - fn deref(&self) -> &semver::Version { - &self.0 - } + fn deref(&self) -> &semver::Version { &self.0 } } impl Deref for CrateVersionReq { type Target = semver::VersionReq; - fn deref(&self) -> &semver::VersionReq { - &self.0 - } + fn deref(&self) -> &semver::VersionReq { &self.0 } } impl Deref for KeywordList { type Target = [Keyword]; - fn deref(&self) -> &[Keyword] { - &self.0 - } + fn deref(&self) -> &[Keyword] { &self.0 } } impl Deref for CategoryList { type Target = [Category]; - fn deref(&self) -> &[Category] { - &self.0 - } + fn deref(&self) -> &[Category] { &self.0 } } diff --git a/src/uploaders.rs b/src/uploaders.rs index f022199090f..f31e045bb20 100644 --- a/src/uploaders.rs +++ b/src/uploaders.rs @@ -14,10 +14,7 @@ use std::io; pub enum Uploader { /// For production usage, uploads and redirects to s3. /// For test usage with a proxy. - S3 { - bucket: s3::Bucket, - proxy: Option, - }, + S3 { bucket: s3::Bucket, proxy: Option }, /// For development usage only: "uploads" crate files to `dist` and serves them /// from there as well to enable local publishing and download @@ -35,13 +32,14 @@ impl Uploader { } } - pub fn crate_location(&self, crate_name: &str, version: &str) -> Option { + pub fn crate_location(&self, crate_name: &str, version: &str) + -> Option { match *self { Uploader::S3 { ref bucket, .. } => { Some(format!("https://{}/{}", bucket.host(), Uploader::crate_path(crate_name, version))) - } + }, Uploader::Local => { Some(format!("/local_uploads/{}", Uploader::crate_path(crate_name, version))) @@ -55,12 +53,7 @@ impl Uploader { format!("crates/{}/{}-{}.crate", name, name, version) } - pub fn upload(&self, - req: &mut Request, - krate: &Crate, - max: u64, - vers: &semver::Version) - -> CargoResult<(Vec, Bomb)> { + pub fn upload(&self, req: &mut Request, krate: &Crate, max: u64, vers: &semver::Version) -> CargoResult<(Vec, Bomb)> { match *self { Uploader::S3 { ref bucket, .. } => { let mut handle = req.app().handle(); @@ -71,44 +64,36 @@ impl Uploader { let mut body = HashingReader::new(body); let mut response = Vec::new(); { - let mut s3req = bucket.put(&mut handle, - &path, - &mut body, - "application/x-tar", - length as u64); - s3req - .write_function(|data| { - response.extend(data); - Ok(data.len()) - }) - .unwrap(); - s3req - .perform() - .chain_error(|| { - internal(&format_args!("failed to upload to S3: `{}`", path)) - })?; + let mut s3req = bucket.put(&mut handle, &path, &mut body, + "application/x-tar", + length as u64); + s3req.write_function(|data| { + response.extend(data); + Ok(data.len()) + }).unwrap(); + s3req.perform().chain_error(|| { + internal(&format_args!("failed to upload to S3: `{}`", path)) + })?; } (response, body.finalize()) }; if handle.response_code().unwrap() != 200 { let response = String::from_utf8_lossy(&response); return Err(internal(&format_args!("failed to get a 200 response from S3: {}", - response))); + response))) } - Ok((cksum, - Bomb { - app: req.app().clone(), - path: Some(path), - })) - } + Ok((cksum, Bomb { + app: req.app().clone(), + path: Some(path), + })) + }, Uploader::Local => { let path = Uploader::crate_path(&krate.name, &vers.to_string()); - let crate_filename = env::current_dir() - .unwrap() - .join("dist") - .join("local_uploads") - .join(path); + let crate_filename = env::current_dir().unwrap() + .join("dist") + .join("local_uploads") + .join(path); let crate_dir = crate_filename.parent().unwrap(); fs::create_dir_all(crate_dir)?; @@ -124,19 +109,12 @@ impl Uploader { body.finalize() }; - Ok((cksum, - Bomb { - app: req.app().clone(), - path: crate_filename.to_str().map(String::from), - })) - } - Uploader::NoOp => { - Ok((vec![], - Bomb { - app: req.app().clone(), - path: None, - })) - } + Ok((cksum, Bomb { + app: req.app().clone(), + path: crate_filename.to_str().map(String::from) + })) + }, + Uploader::NoOp => Ok((vec![], Bomb { app: req.app().clone(), path: None })), } } @@ -146,7 +124,7 @@ impl Uploader { let mut handle = app.handle(); bucket.delete(&mut handle, path).perform()?; Ok(()) - } + }, Uploader::Local => { fs::remove_file(path)?; Ok(()) diff --git a/src/user/middleware.rs b/src/user/middleware.rs index 2b5b256b606..43959aea975 100644 --- a/src/user/middleware.rs +++ b/src/user/middleware.rs @@ -12,11 +12,9 @@ use util::errors::{CargoResult, Unauthorized, ChainError, std_error}; pub struct Middleware; impl conduit_middleware::Middleware for Middleware { - fn before(&self, req: &mut Request) -> Result<(), Box> { + fn before(&self, req: &mut Request) -> Result<(), Box> { // Check if the request has a session cookie with a `user_id` property inside - let id = { - req.session().get("user_id").and_then(|s| s.parse().ok()) - }; + let id = { req.session().get("user_id").and_then(|s| s.parse().ok()) }; let user = match id { @@ -41,10 +39,10 @@ impl conduit_middleware::Middleware for Middleware { let tx = req.tx().map_err(std_error)?; match User::find_by_api_token(tx, headers[0]) { Ok(user) => user, - Err(..) => return Ok(()), + Err(..) => return Ok(()) } } - None => return Ok(()), + None => return Ok(()) } } }; @@ -61,8 +59,6 @@ pub trait RequestUser { impl<'a> RequestUser for Request + 'a { fn user(&self) -> CargoResult<&User> { - self.extensions() - .find::() - .chain_error(|| Unauthorized) + self.extensions().find::().chain_error(|| Unauthorized) } } diff --git a/src/user/mod.rs b/src/user/mod.rs index c377920ea64..d6359cc7c37 100644 --- a/src/user/mod.rs +++ b/src/user/mod.rs @@ -1,5 +1,5 @@ use conduit::{Request, Response}; -use conduit_cookie::RequestSession; +use conduit_cookie::{RequestSession}; use conduit_router::RequestParams; use diesel::prelude::*; use diesel::pg::PgConnection; @@ -51,8 +51,7 @@ impl<'a> NewUser<'a> { email: Option<&'a str>, name: Option<&'a str>, gh_avatar: Option<&'a str>, - gh_access_token: &'a str) - -> Self { + gh_access_token: &'a str) -> Self { NewUser { gh_id: gh_id, gh_login: gh_login, @@ -91,23 +90,26 @@ pub struct EncodableUser { impl User { /// Queries the database for a user with a certain `gh_login` value. - pub fn find_by_login(conn: &GenericConnection, login: &str) -> CargoResult { + pub fn find_by_login(conn: &GenericConnection, + login: &str) -> CargoResult { let stmt = conn.prepare("SELECT * FROM users WHERE gh_login = $1")?; let rows = stmt.query(&[&login])?; - let row = rows.iter().next().chain_error(|| NotFound)?; + let row = rows.iter().next().chain_error(|| { + NotFound + })?; Ok(Model::from_row(&row)) } /// Queries the database for a user with a certain `api_token` value. - pub fn find_by_api_token(conn: &GenericConnection, token: &str) -> CargoResult { + pub fn find_by_api_token(conn: &GenericConnection, + token: &str) -> CargoResult { let stmt = conn.prepare("SELECT * FROM users \ WHERE api_token = $1 LIMIT 1")?; let rows = stmt.query(&[&token])?; - rows.iter() - .next() - .map(|r| Model::from_row(&r)) - .chain_error(|| NotFound) + rows.iter().next().map(|r| Model::from_row(&r)).chain_error(|| { + NotFound + }) } /// Updates a user or inserts a new user into the database. @@ -117,8 +119,7 @@ impl User { email: Option<&str>, name: Option<&str>, avatar: Option<&str>, - access_token: &str) - -> CargoResult { + access_token: &str) -> CargoResult { // TODO: this is racy, but it looks like any other solution is... // interesting! For now just do the racy thing which will report // more errors than it needs to. @@ -131,7 +132,12 @@ impl User { gh_login = $5 WHERE gh_id = $6 RETURNING *")?; - let rows = stmt.query(&[&access_token, &email, &name, &avatar, &login, &id])?; + let rows = stmt.query(&[&access_token, + &email, + &name, + &avatar, + &login, + &id])?; if let Some(ref row) = rows.iter().next() { return Ok(Model::from_row(row)); } @@ -140,22 +146,20 @@ impl User { gh_login, name, gh_avatar, gh_id) VALUES ($1, $2, $3, $4, $5, $6) RETURNING *")?; - let rows = stmt.query(&[&email, &access_token, &login, &name, &avatar, &id])?; - Ok(Model::from_row(&rows.iter() - .next() - .chain_error(|| internal("no user with email we just found"))?)) + let rows = stmt.query(&[&email, + &access_token, + &login, + &name, + &avatar, + &id])?; + Ok(Model::from_row(&rows.iter().next().chain_error(|| { + internal("no user with email we just found") + })?)) } /// Converts this `User` model into an `EncodableUser` for JSON serialization. pub fn encodable(self) -> EncodableUser { - let User { - id, - email, - name, - gh_login, - gh_avatar, - .. - } = self; + let User { id, email, name, gh_login, gh_avatar, .. } = self; let url = format!("https://github.com/{}", gh_login); EncodableUser { id: id, @@ -182,9 +186,7 @@ impl Model for User { } } - fn table_name(_: Option) -> &'static str { - "users" - } + fn table_name(_: Option) -> &'static str { "users" } } /// Handles the `GET /authorize_url` route. @@ -205,20 +207,13 @@ impl Model for User { pub fn github_authorize(req: &mut Request) -> CargoResult { // Generate a random 16 char ASCII string let state: String = thread_rng().gen_ascii_chars().take(16).collect(); - req.session() - .insert("github_oauth_state".to_string(), state.clone()); + req.session().insert("github_oauth_state".to_string(), state.clone()); let url = req.app().github.authorize_url(state.clone()); #[derive(RustcEncodable)] - struct R { - url: String, - state: String, - } - Ok(req.json(&R { - url: url.to_string(), - state: state, - })) + struct R { url: String, state: String } + Ok(req.json(&R { url: url.to_string(), state: state })) } /// Handles the `GET /authorize` route. @@ -261,7 +256,7 @@ pub fn github_access_token(req: &mut Request) -> CargoResult { let session_state = req.session().remove(&"github_oauth_state".to_string()); let session_state = session_state.as_ref().map(|a| &a[..]); if Some(&state[..]) != session_state { - return Err(human("invalid state parameter")); + return Err(human("invalid state parameter")) } } @@ -275,9 +270,7 @@ pub fn github_access_token(req: &mut Request) -> CargoResult { } // Fetch the access token from github using the code we just got - let token = req.app() - .github - .exchange(code.clone()) + let token = req.app().github.exchange(code.clone()) .map_err(|s| human(&s))?; let (handle, resp) = http::github(req.app(), "/user", &token)?; @@ -286,12 +279,14 @@ pub fn github_access_token(req: &mut Request) -> CargoResult { let user = User::find_or_insert(req.tx()?, ghuser.id, &ghuser.login, - ghuser.email.as_ref().map(|s| &s[..]), - ghuser.name.as_ref().map(|s| &s[..]), - ghuser.avatar_url.as_ref().map(|s| &s[..]), + ghuser.email.as_ref() + .map(|s| &s[..]), + ghuser.name.as_ref() + .map(|s| &s[..]), + ghuser.avatar_url.as_ref() + .map(|s| &s[..]), &token.access_token)?; - req.session() - .insert("user_id".to_string(), user.id.to_string()); + req.session().insert("user_id".to_string(), user.id.to_string()); req.mut_extensions().insert(user); me(req) } @@ -308,17 +303,13 @@ pub fn reset_token(req: &mut Request) -> CargoResult { let conn = req.tx()?; let rows = conn.query("UPDATE users SET api_token = DEFAULT \ - WHERE id = $1 RETURNING api_token", - &[&user.id])?; - let token = rows.iter() - .next() + WHERE id = $1 RETURNING api_token", &[&user.id])?; + let token = rows.iter().next() .map(|r| r.get("api_token")) .chain_error(|| NotFound)?; #[derive(RustcEncodable)] - struct R { - api_token: String, - } + struct R { api_token: String } Ok(req.json(&R { api_token: token })) } @@ -327,15 +318,9 @@ pub fn me(req: &mut Request) -> CargoResult { let user = req.user()?; #[derive(RustcEncodable)] - struct R { - user: EncodableUser, - api_token: String, - } + struct R { user: EncodableUser, api_token: String } let token = user.api_token.clone(); - Ok(req.json(&R { - user: user.clone().encodable(), - api_token: token, - })) + Ok(req.json(&R{ user: user.clone().encodable(), api_token: token })) } /// Handles the `GET /users/:user_id` route. @@ -344,13 +329,14 @@ pub fn show(req: &mut Request) -> CargoResult { let name = &req.params()["user_id"]; let conn = req.db_conn()?; - let user = users.filter(gh_login.eq(name)).first::(&*conn)?; + let user = users.filter(gh_login.eq(name)) + .first::(&*conn)?; #[derive(RustcEncodable)] struct R { user: EncodableUser, } - Ok(req.json(&R { user: user.encodable() })) + Ok(req.json(&R{ user: user.encodable() })) } @@ -363,23 +349,27 @@ pub fn updates(req: &mut Request) -> CargoResult { let (offset, limit) = req.pagination(10, 100)?; let conn = req.db_conn()?; - let followed_crates = Follow::belonging_to(user).select(follows::crate_id); - let data = versions::table - .inner_join(crates::table) + let followed_crates = Follow::belonging_to(user) + .select(follows::crate_id); + let data = versions::table.inner_join(crates::table) .filter(crates::id.eq(any(followed_crates))) .order(versions::created_at.desc()) .limit(limit) .offset(offset) - .select((versions::all_columns, crates::name, sql::("COUNT(*) OVER ()"))) + .select(( + versions::all_columns, + crates::name, + sql::("COUNT(*) OVER ()"), + )) .load::<(Version, String, i64)>(&*conn)?; let more = data.get(0) .map(|&(_, _, count)| count > offset + limit) .unwrap_or(false); - let versions = data.into_iter() - .map(|(version, crate_name, _)| version.encodable(&crate_name)) - .collect(); + let versions = data.into_iter().map(|(version, crate_name, _)| { + version.encodable(&crate_name) + }).collect(); #[derive(RustcEncodable)] struct R { @@ -387,13 +377,8 @@ pub fn updates(req: &mut Request) -> CargoResult { meta: Meta, } #[derive(RustcEncodable)] - struct Meta { - more: bool, - } - Ok(req.json(&R { - versions: versions, - meta: Meta { more: more }, - })) + struct Meta { more: bool } + Ok(req.json(&R{ versions: versions, meta: Meta { more: more } })) } #[cfg(test)] @@ -416,11 +401,9 @@ mod tests { fn new_users_have_different_api_tokens() { let conn = connection(); let user1 = NewUser::new(1, "foo", None, None, None, "foo") - .create_or_update(&conn) - .unwrap(); + .create_or_update(&conn).unwrap(); let user2 = NewUser::new(2, "bar", None, None, None, "bar") - .create_or_update(&conn) - .unwrap(); + .create_or_update(&conn).unwrap(); assert_ne!(user1.id, user2.id); assert_ne!(user1.api_token, user2.api_token); @@ -431,12 +414,10 @@ mod tests { fn updating_existing_user_doesnt_change_api_token() { let conn = connection(); let user_after_insert = NewUser::new(1, "foo", None, None, None, "foo") - .create_or_update(&conn) - .unwrap(); + .create_or_update(&conn).unwrap(); let original_token = user_after_insert.api_token; NewUser::new(1, "bar", None, None, None, "bar_token") - .create_or_update(&conn) - .unwrap(); + .create_or_update(&conn).unwrap(); let mut users = users::table.load::(&conn).unwrap(); assert_eq!(1, users.len()); let user = users.pop().unwrap(); diff --git a/src/util/errors.rs b/src/util/errors.rs index ffaae1a0e5c..6fa45c96d83 100644 --- a/src/util/errors.rs +++ b/src/util/errors.rs @@ -3,41 +3,30 @@ use std::error::Error; use std::fmt; use conduit::Response; -use diesel::result::Error as DieselError; +use diesel::result::{Error as DieselError}; use util::json_response; -#[derive(RustcEncodable)] -struct StringError { - detail: String, -} -#[derive(RustcEncodable)] -struct Bad { - errors: Vec, -} +#[derive(RustcEncodable)] struct StringError { detail: String } +#[derive(RustcEncodable)] struct Bad { errors: Vec } // ============================================================================= // CargoError trait pub trait CargoError: Send + fmt::Display + 'static { fn description(&self) -> &str; - fn cause(&self) -> Option<&(CargoError)> { - None - } + fn cause(&self) -> Option<&(CargoError)> { None } fn response(&self) -> Option { if self.human() { Some(json_response(&Bad { - errors: - vec![StringError { detail: self.description().to_string() }], - })) + errors: vec![StringError { detail: self.description().to_string() }] + })) } else { self.cause().and_then(|cause| cause.response()) } } - fn human(&self) -> bool { - false - } + fn human(&self) -> bool { false } } impl fmt::Debug for Box { @@ -47,32 +36,16 @@ impl fmt::Debug for Box { } impl CargoError for Box { - fn description(&self) -> &str { - (**self).description() - } - fn cause(&self) -> Option<&CargoError> { - (**self).cause() - } - fn human(&self) -> bool { - (**self).human() - } - fn response(&self) -> Option { - (**self).response() - } + fn description(&self) -> &str { (**self).description() } + fn cause(&self) -> Option<&CargoError> { (**self).cause() } + fn human(&self) -> bool { (**self).human() } + fn response(&self) -> Option { (**self).response() } } impl CargoError for Box { - fn description(&self) -> &str { - (**self).description() - } - fn cause(&self) -> Option<&CargoError> { - (**self).cause() - } - fn human(&self) -> bool { - (**self).human() - } - fn response(&self) -> Option { - (**self).response() - } + fn description(&self) -> &str { (**self).description() } + fn cause(&self) -> Option<&CargoError> { (**self).cause() } + fn human(&self) -> bool { (**self).human() } + fn response(&self) -> Option { (**self).response() } } pub type CargoResult = Result>; @@ -82,8 +55,7 @@ pub type CargoResult = Result>; pub trait ChainError { fn chain_error(self, callback: F) -> CargoResult - where E: CargoError, - F: FnOnce() -> E; + where E: CargoError, F: FnOnce() -> E; } struct ChainedError { @@ -91,13 +63,9 @@ struct ChainedError { cause: Box, } -impl ChainError for F - where F: FnOnce() -> CargoResult -{ +impl ChainError for F where F: FnOnce() -> CargoResult { fn chain_error(self, callback: C) -> CargoResult - where E: CargoError, - C: FnOnce() -> E - { + where E: CargoError, C: FnOnce() -> E { self().chain_error(callback) } } @@ -105,23 +73,19 @@ impl ChainError for F impl ChainError for Result { #[allow(trivial_casts)] fn chain_error(self, callback: C) -> CargoResult - where E2: CargoError, - C: FnOnce() -> E2 - { + where E2: CargoError, C: FnOnce() -> E2 { self.map_err(move |err| { - Box::new(ChainedError { - error: callback(), - cause: Box::new(err), - }) as Box - }) + Box::new(ChainedError { + error: callback(), + cause: Box::new(err), + }) as Box + }) } } impl ChainError for Option { fn chain_error(self, callback: C) -> CargoResult - where E: CargoError, - C: FnOnce() -> E - { + where E: CargoError, C: FnOnce() -> E { match self { Some(t) => Ok(t), None => Err(Box::new(callback())), @@ -130,18 +94,10 @@ impl ChainError for Option { } impl CargoError for ChainedError { - fn description(&self) -> &str { - self.error.description() - } - fn cause(&self) -> Option<&CargoError> { - Some(&*self.cause) - } - fn response(&self) -> Option { - self.error.response() - } - fn human(&self) -> bool { - self.error.human() - } + fn description(&self) -> &str { self.error.description() } + fn cause(&self) -> Option<&CargoError> { Some(&*self.cause) } + fn response(&self) -> Option { self.error.response() } + fn human(&self) -> bool { self.error.human() } } impl fmt::Display for ChainedError { @@ -163,9 +119,7 @@ impl From for Box { struct Shim(E); impl CargoError for Shim { - fn description(&self) -> &str { - Error::description(&self.0) - } + fn description(&self) -> &str { Error::description(&self.0) } } impl fmt::Display for Shim { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -177,14 +131,10 @@ impl From for Box { } impl CargoError for ::curl::Error { - fn description(&self) -> &str { - Error::description(self) - } + fn description(&self) -> &str { Error::description(self) } } impl CargoError for ::rustc_serialize::json::DecoderError { - fn description(&self) -> &str { - Error::description(self) - } + fn description(&self) -> &str { Error::description(self) } } // ============================================================================= @@ -208,27 +158,20 @@ impl fmt::Display for ConcreteCargoError { } impl CargoError for ConcreteCargoError { - fn description(&self) -> &str { - &self.description - } - fn cause(&self) -> Option<&CargoError> { - self.cause.as_ref().map(|c| &**c) - } - fn human(&self) -> bool { - self.human - } + fn description(&self) -> &str { &self.description } + fn cause(&self) -> Option<&CargoError> { self.cause.as_ref().map(|c| &**c) } + fn human(&self) -> bool { self.human } } pub struct NotFound; impl CargoError for NotFound { - fn description(&self) -> &str { - "not found" - } + fn description(&self) -> &str { "not found" } fn response(&self) -> Option { - let mut response = - json_response(&Bad { errors: vec![StringError { detail: "Not Found".to_string() }] }); + let mut response = json_response(&Bad { + errors: vec![StringError { detail: "Not Found".to_string() }], + }); response.status = (404, "Not Found"); Some(response) } @@ -243,16 +186,14 @@ impl fmt::Display for NotFound { pub struct Unauthorized; impl CargoError for Unauthorized { - fn description(&self) -> &str { - "unauthorized" - } + fn description(&self) -> &str { "unauthorized" } fn response(&self) -> Option { let mut response = json_response(&Bad { - errors: vec![StringError { + errors: vec![StringError { detail: "must be logged in to perform that action".to_string(), }], - }); + }); response.status = (403, "Forbidden"); Some(response) } @@ -266,38 +207,36 @@ impl fmt::Display for Unauthorized { pub fn internal_error(error: &str, detail: &str) -> Box { Box::new(ConcreteCargoError { - description: error.to_string(), - detail: Some(detail.to_string()), - cause: None, - human: false, - }) + description: error.to_string(), + detail: Some(detail.to_string()), + cause: None, + human: false, + }) } pub fn internal(error: &S) -> Box { Box::new(ConcreteCargoError { - description: error.to_string(), - detail: None, - cause: None, - human: false, - }) + description: error.to_string(), + detail: None, + cause: None, + human: false, + }) } pub fn human(error: &S) -> Box { Box::new(ConcreteCargoError { - description: error.to_string(), - detail: None, - cause: None, - human: true, - }) + description: error.to_string(), + detail: None, + cause: None, + human: true, + }) } -pub fn std_error(e: Box) -> Box { +pub fn std_error(e: Box) -> Box { #[derive(Debug)] struct E(Box); impl Error for E { - fn description(&self) -> &str { - self.0.description() - } + fn description(&self) -> &str { self.0.description() } } impl fmt::Display for E { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/util/head.rs b/src/util/head.rs index 3202c4e4ec1..5f931ab0ee1 100644 --- a/src/util/head.rs +++ b/src/util/head.rs @@ -18,23 +18,19 @@ impl AroundMiddleware for Head { } impl Handler for Head { - fn call(&self, req: &mut Request) -> Result> { + fn call(&self, req: &mut Request) -> Result> { if req.method() == Method::Head { let mut req = RequestProxy { other: req, path: None, method: Some(Method::Get), }; - self.handler - .as_ref() - .unwrap() - .call(&mut req) - .map(|r| { - Response { - body: Box::new(io::empty()), - ..r - } - }) + self.handler.as_ref().unwrap().call(&mut req).map(|r| { + Response { + body: Box::new(io::empty()), + ..r + } + }) } else { self.handler.as_ref().unwrap().call(req) } diff --git a/src/util/io_util.rs b/src/util/io_util.rs index 749fbab5634..9ebc2308043 100644 --- a/src/util/io_util.rs +++ b/src/util/io_util.rs @@ -16,7 +16,8 @@ impl Read for LimitErrorReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { match self.inner.read(buf) { Ok(0) if self.inner.limit() == 0 => { - Err(io::Error::new(io::ErrorKind::Other, "maximum limit reached when reading")) + Err(io::Error::new(io::ErrorKind::Other, + "maximum limit reached when reading")) } e => e, } @@ -26,14 +27,19 @@ impl Read for LimitErrorReader { pub fn read_le_u32(r: &mut R) -> io::Result { let mut b = [0; 4]; read_fill(r, &mut b)?; - Ok((b[0] as u32) | ((b[1] as u32) << 8) | ((b[2] as u32) << 16) | ((b[3] as u32) << 24)) + Ok( (b[0] as u32) | + ((b[1] as u32) << 8) | + ((b[2] as u32) << 16) | + ((b[3] as u32) << 24)) } -pub fn read_fill(r: &mut R, mut slice: &mut [u8]) -> io::Result<()> { +pub fn read_fill(r: &mut R, mut slice: &mut [u8]) + -> io::Result<()> { while !slice.is_empty() { let n = r.read(slice)?; if n == 0 { - return Err(io::Error::new(io::ErrorKind::Other, "end of file reached")); + return Err(io::Error::new(io::ErrorKind::Other, + "end of file reached")) } slice = &mut mem::replace(&mut slice, &mut [])[n..]; } diff --git a/src/util/lazy_cell.rs b/src/util/lazy_cell.rs index e530473d597..9ab36f7430f 100644 --- a/src/util/lazy_cell.rs +++ b/src/util/lazy_cell.rs @@ -33,9 +33,7 @@ impl LazyCell { } /// Test whether this cell has been previously filled. - pub fn filled(&self) -> bool { - self.inner.borrow().is_some() - } + pub fn filled(&self) -> bool { self.inner.borrow().is_some() } /// Borrows the contents of this lazy cell for the duration of the cell /// itself. @@ -45,7 +43,7 @@ impl LazyCell { pub fn borrow(&self) -> Option<&T> { match *self.inner.borrow() { Some(ref inner) => unsafe { Some(mem::transmute(inner)) }, - None => None, + None => None } } diff --git a/src/util/mod.rs b/src/util/mod.rs index f4abe88be61..866d1256111 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -14,7 +14,7 @@ use self::errors::NotFound; pub use self::errors::{CargoError, CargoResult, internal, human, internal_error}; pub use self::errors::{ChainError, std_error}; -pub use self::hasher::HashingReader; +pub use self::hasher::{HashingReader}; pub use self::head::Head; pub use self::io_util::{LimitErrorReader, read_le_u32, read_fill}; pub use self::lazy_cell::LazyCell; @@ -44,24 +44,26 @@ pub fn json_response(t: &T) -> Response { vec!["application/json; charset=utf-8".to_string()]); headers.insert("Content-Length".to_string(), vec![json.len().to_string()]); return Response { - status: (200, "OK"), - headers: headers, - body: Box::new(Cursor::new(json.into_bytes())), - }; + status: (200, "OK"), + headers: headers, + body: Box::new(Cursor::new(json.into_bytes())), + }; fn fixup(json: Json) -> Json { match json { Json::Object(object) => { - Json::Object(object - .into_iter() - .map(|(k, v)| { - let k = - if k == "krate" { "crate".to_string() } else { k }; - (k, fixup(v)) - }) - .collect()) + Json::Object(object.into_iter().map(|(k, v)| { + let k = if k == "krate" { + "crate".to_string() + } else { + k + }; + (k, fixup(v)) + }).collect()) + } + Json::Array(list) => { + Json::Array(list.into_iter().map(fixup).collect()) } - Json::Array(list) => Json::Array(list.into_iter().map(fixup).collect()), j => j, } } @@ -74,7 +76,8 @@ impl<'a> RequestUtils for Request + 'a { } fn query(&self) -> HashMap { - url::form_urlencoded::parse(self.query_string().unwrap_or("").as_bytes()) + url::form_urlencoded::parse(self.query_string().unwrap_or("") + .as_bytes()) .map(|(a, b)| (a.into_owned(), b.into_owned())) .collect() } @@ -90,27 +93,22 @@ impl<'a> RequestUtils for Request + 'a { } fn wants_json(&self) -> bool { - self.headers() - .find("Accept") - .map(|accept| accept.iter().any(|s| s.contains("json"))) - .unwrap_or(false) + self.headers().find("Accept").map(|accept| { + accept.iter().any(|s| s.contains("json")) + }).unwrap_or(false) } fn pagination(&self, default: usize, max: usize) -> CargoResult<(i64, i64)> { let query = self.query(); - let page = query - .get("page") - .and_then(|s| s.parse::().ok()) - .unwrap_or(1); - let limit = query - .get("per_page") - .and_then(|s| s.parse::().ok()) - .unwrap_or(default); + let page = query.get("page").and_then(|s| s.parse::().ok()) + .unwrap_or(1); + let limit = query.get("per_page").and_then(|s| s.parse::().ok()) + .unwrap_or(default); if limit > max { - return Err(human(&format_args!("cannot request more than {} items", max))); + return Err(human(&format_args!("cannot request more than {} items", max))) } if page == 0 { - return Err(human("page indexing starts from 1, page 0 is invalid")); + return Err(human("page indexing starts from 1, page 0 is invalid")) } Ok((((page - 1) * limit) as i64, limit as i64)) } @@ -119,7 +117,7 @@ impl<'a> RequestUtils for Request + 'a { pub struct C(pub fn(&mut Request) -> CargoResult); impl Handler for C { - fn call(&self, req: &mut Request) -> Result> { + fn call(&self, req: &mut Request) -> Result> { let C(f) = *self; match f(req) { Ok(resp) => { @@ -129,7 +127,7 @@ impl Handler for C { Err(e) => { match e.response() { Some(response) => Ok(response), - None => Err(std_error(e)), + None => Err(std_error(e)) } } } @@ -139,21 +137,21 @@ impl Handler for C { pub struct R(pub Arc); impl Handler for R { - fn call(&self, req: &mut Request) -> Result> { + fn call(&self, req: &mut Request) -> Result> { let path = req.params()["path"].to_string(); let R(ref sub_router) = *self; sub_router.call(&mut RequestProxy { - other: req, - path: Some(&path), - method: None, - }) + other: req, + path: Some(&path), + method: None, + }) } } pub struct R404(pub RouteBuilder); impl Handler for R404 { - fn call(&self, req: &mut Request) -> Result> { + fn call(&self, req: &mut Request) -> Result> { let R404(ref router) = *self; match router.recognize(&req.method(), req.path()) { Ok(m) => { diff --git a/src/util/request_proxy.rs b/src/util/request_proxy.rs index 8c1929db133..e29063abdd0 100644 --- a/src/util/request_proxy.rs +++ b/src/util/request_proxy.rs @@ -19,16 +19,10 @@ impl<'a> Request for RequestProxy<'a> { self.other.conduit_version() } fn method(&self) -> conduit::Method { - self.method - .clone() - .unwrap_or_else(|| self.other.method().clone()) - } - fn scheme(&self) -> conduit::Scheme { - self.other.scheme() - } - fn host(&self) -> conduit::Host { - self.other.host() + self.method.clone().unwrap_or_else(|| self.other.method().clone()) } + fn scheme(&self) -> conduit::Scheme { self.other.scheme() } + fn host(&self) -> conduit::Host { self.other.host() } fn virtual_root(&self) -> Option<&str> { self.other.virtual_root() } @@ -38,18 +32,14 @@ impl<'a> Request for RequestProxy<'a> { fn query_string(&self) -> Option<&str> { self.other.query_string() } - fn remote_addr(&self) -> SocketAddr { - self.other.remote_addr() - } + fn remote_addr(&self) -> SocketAddr { self.other.remote_addr() } fn content_length(&self) -> Option { self.other.content_length() } fn headers(&self) -> &conduit::Headers { self.other.headers() } - fn body(&mut self) -> &mut Read { - self.other.body() - } + fn body(&mut self) -> &mut Read { self.other.body() } fn extensions(&self) -> &conduit::Extensions { self.other.extensions() } diff --git a/src/version.rs b/src/version.rs index 8a37326f1b3..218d9b36b4b 100644 --- a/src/version.rs +++ b/src/version.rs @@ -46,7 +46,7 @@ pub struct NewVersion { } pub struct Author { - pub name: String, + pub name: String } #[derive(RustcEncodable, RustcDecodable)] @@ -95,10 +95,9 @@ impl Version { VALUES ($1, $2, $3) \ RETURNING *")?; let rows = stmt.query(&[&crate_id, &num, &features])?; - let ret: Version = - Model::from_row(&rows.iter() - .next() - .chain_error(|| internal("no version returned"))?); + let ret: Version = Model::from_row(&rows.iter().next().chain_error(|| { + internal("no version returned") + })?); for author in authors { ret.add_author(conn, author)?; } @@ -110,16 +109,8 @@ impl Version { } pub fn encodable(self, crate_name: &str) -> EncodableVersion { - let Version { - id, - num, - updated_at, - created_at, - downloads, - features, - yanked, - .. - } = self; + let Version { id, num, updated_at, created_at, + downloads, features, yanked, .. } = self; let num = num.to_string(); EncodableVersion { dl_path: format!("/api/v1/crates/{}/{}/download", crate_name, num), @@ -142,7 +133,8 @@ impl Version { } /// Returns (dependency, crate dependency name) - pub fn dependencies(&self, conn: &PgConnection) -> QueryResult> { + pub fn dependencies(&self, conn: &PgConnection) + -> QueryResult> { Dependency::belonging_to(self) .inner_join(crates::table) .select((dependencies::all_columns, crates::name)) @@ -155,15 +147,16 @@ impl Version { WHERE version_id = $1 ORDER BY name ASC")?; let rows = stmt.query(&[&self.id])?; - Ok(rows.into_iter() - .map(|row| Author { name: row.get("name") }) - .collect()) + Ok(rows.into_iter().map(|row| { + Author { name: row.get("name") } + }).collect()) } - pub fn add_author(&self, conn: &GenericConnection, name: &str) -> CargoResult<()> { + pub fn add_author(&self, + conn: &GenericConnection, + name: &str) -> CargoResult<()> { conn.execute("INSERT INTO version_authors (version_id, name) - VALUES ($1, $2)", - &[&self.id, &name])?; + VALUES ($1, $2)", &[&self.id, &name])?; Ok(()) } @@ -173,35 +166,33 @@ impl Version { Ok(()) } - pub fn max(versions: T) -> semver::Version - where T: IntoIterator + pub fn max(versions: T) -> semver::Version where + T: IntoIterator, { - versions - .into_iter() + versions.into_iter() .max() - .unwrap_or_else(|| { - semver::Version { - major: 0, - minor: 0, - patch: 0, - pre: vec![], - build: vec![], - } + .unwrap_or_else(|| semver::Version { + major: 0, + minor: 0, + patch: 0, + pre: vec![], + build: vec![], }) } } impl NewVersion { - pub fn new(crate_id: i32, - num: &semver::Version, - features: &HashMap>) - -> CargoResult { + pub fn new( + crate_id: i32, + num: &semver::Version, + features: &HashMap>, + ) -> CargoResult { let features = json::encode(features)?; Ok(NewVersion { - crate_id: crate_id, - num: num.to_string(), - features: features, - }) + crate_id: crate_id, + num: num.to_string(), + features: features, + }) } pub fn save(&self, conn: &PgConnection, authors: &[String]) -> CargoResult { @@ -209,8 +200,7 @@ impl NewVersion { use diesel::expression::dsl::exists; use schema::versions::dsl::*; - let already_uploaded = versions - .filter(crate_id.eq(self.crate_id)) + let already_uploaded = versions.filter(crate_id.eq(self.crate_id)) .filter(num.eq(&self.num)); if select(exists(already_uploaded)).get_result(conn)? { return Err(human(&format_args!("crate version `{}` is already \ @@ -218,20 +208,15 @@ impl NewVersion { } conn.transaction(|| { - let version = insert(self).into(versions).get_result::(conn)?; - - let new_authors = authors - .iter() - .map(|s| { - NewAuthor { - version_id: version.id, - name: &*s, - } - }) - .collect::>(); - - insert(&new_authors) - .into(version_authors::table) + let version = insert(self).into(versions) + .get_result::(conn)?; + + let new_authors = authors.iter().map(|s| NewAuthor { + version_id: version.id, + name: &*s, + }).collect::>(); + + insert(&new_authors).into(version_authors::table) .execute(conn)?; Ok(version) }) @@ -249,9 +234,9 @@ impl Queryable for Version { type Row = (i32, i32, String, Timespec, Timespec, i32, Option, bool); fn build(row: Self::Row) -> Self { - let features = row.6 - .map(|s| json::decode(&s).unwrap()) - .unwrap_or_else(HashMap::new); + let features = row.6.map(|s| { + json::decode(&s).unwrap() + }).unwrap_or_else(HashMap::new); Version { id: row.0, crate_id: row.1, @@ -269,9 +254,9 @@ impl Model for Version { fn from_row(row: &Row) -> Version { let num: String = row.get("num"); let features: Option = row.get("features"); - let features = features - .map(|s| json::decode(&s).unwrap()) - .unwrap_or_else(HashMap::new); + let features = features.map(|s| { + json::decode(&s).unwrap() + }).unwrap_or_else(HashMap::new); Version { id: row.get("id"), crate_id: row.get("crate_id"), @@ -283,9 +268,7 @@ impl Model for Version { yanked: row.get("yanked"), } } - fn table_name(_: Option) -> &'static str { - "versions" - } + fn table_name(_: Option) -> &'static str { "versions" } } /// Handles the `GET /versions` route. @@ -294,10 +277,15 @@ pub fn index(req: &mut Request) -> CargoResult { let conn = req.tx()?; // Extract all ids requested. - let query = url::form_urlencoded::parse(req.query_string().unwrap_or("").as_bytes()); - let ids = query - .filter_map(|(ref a, ref b)| if *a == "ids[]" { b.parse().ok() } else { None }) - .collect::>(); + let query = url::form_urlencoded::parse(req.query_string().unwrap_or("") + .as_bytes()); + let ids = query.filter_map(|(ref a, ref b)| { + if *a == "ids[]" { + b.parse().ok() + } else { + None + } + }).collect::>(); // Load all versions // @@ -318,9 +306,7 @@ pub fn index(req: &mut Request) -> CargoResult { } #[derive(RustcEncodable)] - struct R { - versions: Vec, - } + struct R { versions: Vec } Ok(req.json(&R { versions: versions })) } @@ -332,8 +318,7 @@ pub fn show(req: &mut Request) -> CargoResult { let id = &req.params()["version_id"]; let id = id.parse().unwrap_or(0); let conn = req.db_conn()?; - versions::table - .find(id) + versions::table.find(id) .inner_join(crates::table) .select((versions::all_columns, ::krate::ALL_COLUMNS)) .first(&*conn)? @@ -341,25 +326,23 @@ pub fn show(req: &mut Request) -> CargoResult { }; #[derive(RustcEncodable)] - struct R { - version: EncodableVersion, - } + struct R { version: EncodableVersion } Ok(req.json(&R { version: version.encodable(&krate.name) })) } fn version_and_crate_old(req: &mut Request) -> CargoResult<(Version, Crate)> { let crate_name = &req.params()["crate_id"]; let semver = &req.params()["version"]; - let semver = semver::Version::parse(semver) - .map_err(|_| human(&format_args!("invalid semver: {}", semver)))?; + let semver = semver::Version::parse(semver).map_err(|_| { + human(&format_args!("invalid semver: {}", semver)) + })?; let tx = req.tx()?; let krate = Crate::find_by_name(tx, crate_name)?; let version = Version::find_by_num(tx, krate.id, &semver)?; - let version = version - .chain_error(|| { - human(&format_args!("crate `{}` does not have a version `{}`", + let version = version.chain_error(|| { + human(&format_args!("crate `{}` does not have a version `{}`", crate_name, semver)) - })?; + })?; Ok((version, krate)) } @@ -375,9 +358,9 @@ fn version_and_crate(req: &mut Request) -> CargoResult<(Version, Crate)> { .filter(versions::num.eq(semver)) .first(&*conn) .map_err(|_| { - human(&format_args!("crate `{}` does not have a version `{}`", + human(&format_args!("crate `{}` does not have a version `{}`", crate_name, semver)) - })?; + })?; Ok((version, krate)) } @@ -386,15 +369,13 @@ pub fn dependencies(req: &mut Request) -> CargoResult { let (version, _) = version_and_crate(req)?; let conn = req.db_conn()?; let deps = version.dependencies(&*conn)?; - let deps = deps.into_iter() - .map(|(dep, crate_name)| dep.encodable(&crate_name, None)) - .collect(); + let deps = deps.into_iter().map(|(dep, crate_name)| { + dep.encodable(&crate_name, None) + }).collect(); #[derive(RustcEncodable)] - struct R { - dependencies: Vec, - } - Ok(req.json(&R { dependencies: deps })) + struct R { dependencies: Vec } + Ok(req.json(&R{ dependencies: deps })) } /// Handles the `GET /crates/:crate_id/:version/downloads` route. @@ -402,11 +383,9 @@ pub fn downloads(req: &mut Request) -> CargoResult { use diesel::expression::dsl::date; let (version, _) = version_and_crate(req)?; let conn = req.db_conn()?; - let cutoff_end_date = req.query() - .get("before_date") + let cutoff_end_date = req.query().get("before_date") .and_then(|d| strptime(d, "%Y-%m-%d").ok()) - .unwrap_or_else(now_utc) - .to_timespec(); + .unwrap_or_else(now_utc).to_timespec(); let cutoff_start_date = cutoff_end_date + Duration::days(-89); let downloads = VersionDownload::belonging_to(&version) @@ -418,10 +397,8 @@ pub fn downloads(req: &mut Request) -> CargoResult { .collect(); #[derive(RustcEncodable)] - struct R { - version_downloads: Vec, - } - Ok(req.json(&R { version_downloads: downloads })) + struct R { version_downloads: Vec } + Ok(req.json(&R{ version_downloads: downloads })) } /// Handles the `GET /crates/:crate_id/:version/authors` route. @@ -434,18 +411,10 @@ pub fn authors(req: &mut Request) -> CargoResult { // This was never implemented. This complicated return struct // is all that is left, hear for backwards compatibility. #[derive(RustcEncodable)] - struct R { - users: Vec<::user::EncodableUser>, - meta: Meta, - } + struct R { users: Vec<::user::EncodableUser>, meta: Meta } #[derive(RustcEncodable)] - struct Meta { - names: Vec, - } - Ok(req.json(&R { - users: vec![], - meta: Meta { names: names }, - })) + struct Meta { names: Vec } + Ok(req.json(&R{ users: vec![], meta: Meta { names: names } })) } /// Handles the `DELETE /crates/:crate_id/:version/yank` route. @@ -464,22 +433,19 @@ fn modify_yank(req: &mut Request, yanked: bool) -> CargoResult { let conn = req.db_conn()?; let owners = krate.owners(&conn)?; if rights(req.app(), &owners, user)? < Rights::Publish { - return Err(human("must already be an owner to yank or unyank")); + return Err(human("must already be an owner to yank or unyank")) } if version.yanked != yanked { conn.transaction::<_, Box, _>(|| { - diesel::update(&version) - .set(versions::yanked.eq(yanked)) - .execute(&*conn)?; - git::yank(&**req.app(), &krate.name, &version.num, yanked)?; - Ok(()) - })?; + diesel::update(&version).set(versions::yanked.eq(yanked)) + .execute(&*conn)?; + git::yank(&**req.app(), &krate.name, &version.num, yanked)?; + Ok(()) + })?; } #[derive(RustcEncodable)] - struct R { - ok: bool, - } - Ok(req.json(&R { ok: true })) + struct R { ok: bool } + Ok(req.json(&R{ ok: true })) } From ae0683806b655bd644a424eacd56827c6038af71 Mon Sep 17 00:00:00 2001 From: Vignesh Date: Tue, 13 Jun 2017 13:57:17 +1000 Subject: [PATCH 03/14] Initial commit --- .rustfmt.toml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .rustfmt.toml diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 00000000000..dabeeeccb52 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,9 @@ +fn_args_layout = "Block" +array_layout = "Block" +control_style = "Rfc" +where_style = "Rfc" +generics_indent = "Block" +fn_call_style = "Block" +combine_control_expr = true +fn_args_paren_newline = false +max_width = 140 \ No newline at end of file From 587d1e7bf15955504c2a009a0b40e6d3ac5275c9 Mon Sep 17 00:00:00 2001 From: Vignesh Date: Tue, 13 Jun 2017 13:57:28 +1000 Subject: [PATCH 04/14] cargo fmt --- build.rs | 6 +- src/app.rs | 10 +- src/badge.rs | 77 +-- src/bin/delete-crate.rs | 92 ++- src/bin/delete-version.rs | 52 +- src/bin/fill-in-user-id.rs | 29 +- src/bin/populate.rs | 12 +- src/bin/server.rs | 54 +- src/bin/transfer-crates.rs | 32 +- src/bin/update-downloads.rs | 336 ++++++++--- src/categories.rs | 59 +- src/category.rs | 354 +++++++----- src/db.rs | 46 +- src/dependency.rs | 138 +++-- src/dist.rs | 24 +- src/download.rs | 21 +- src/git.rs | 134 +++-- src/http.rs | 52 +- src/keyword.rs | 94 ++-- src/krate.rs | 1062 +++++++++++++++++++++-------------- src/lib.rs | 62 +- src/owner.rs | 144 +++-- src/tests/all.rs | 281 +++++---- src/tests/badge.rs | 207 ++----- src/tests/category.rs | 45 +- src/tests/git.rs | 27 +- src/tests/keyword.rs | 20 +- src/tests/krate.rs | 609 ++++++++++++++------ src/tests/record.rs | 255 +++++---- src/tests/team.rs | 304 ++++++---- src/tests/user.rs | 97 ++-- src/tests/version.rs | 11 +- src/upload.rs | 72 ++- src/uploaders.rs | 105 ++-- src/user/middleware.rs | 14 +- src/user/mod.rs | 234 +++++--- src/util/errors.rs | 204 ++++--- src/util/head.rs | 20 +- src/util/io_util.rs | 16 +- src/util/lazy_cell.rs | 6 +- src/util/mod.rs | 85 +-- src/util/request_proxy.rs | 20 +- src/version.rs | 317 +++++++---- 43 files changed, 3584 insertions(+), 2255 deletions(-) diff --git a/build.rs b/build.rs index 70c9bb1d8e4..6f3b30a0661 100644 --- a/build.rs +++ b/build.rs @@ -11,10 +11,8 @@ fn main() { if env::var("PROFILE") == Ok("debug".into()) { let _ = dotenv(); if let Ok(database_url) = env::var("TEST_DATABASE_URL") { - let connection = PgConnection::establish(&database_url) - .expect("Could not connect to TEST_DATABASE_URL"); - run_pending_migrations(&connection) - .expect("Error running migrations"); + let connection = PgConnection::establish(&database_url).expect("Could not connect to TEST_DATABASE_URL"); + run_pending_migrations(&connection).expect("Error running migrations"); } } } diff --git a/src/app.rs b/src/app.rs index b38ee8412a1..a19f2b03275 100644 --- a/src/app.rs +++ b/src/app.rs @@ -34,7 +34,7 @@ pub struct App { /// The `AppMiddleware` injects an `App` instance into the `Request` extensions pub struct AppMiddleware { - app: Arc + app: Arc, } impl App { @@ -105,13 +105,12 @@ impl AppMiddleware { } impl Middleware for AppMiddleware { - fn before(&self, req: &mut Request) -> Result<(), Box> { + fn before(&self, req: &mut Request) -> Result<(), Box> { req.mut_extensions().insert(self.app.clone()); Ok(()) } - fn after(&self, req: &mut Request, res: Result>) - -> Result> { + fn after(&self, req: &mut Request, res: Result>) -> Result> { req.mut_extensions().pop::>().unwrap(); res } @@ -124,7 +123,6 @@ pub trait RequestApp { impl RequestApp for T { fn app(&self) -> &Arc { - self.extensions().find::>() - .expect("Missing app") + self.extensions().find::>().expect("Missing app") } } diff --git a/src/badge.rs b/src/badge.rs index bcb627b32ed..e7089f48d63 100644 --- a/src/badge.rs +++ b/src/badge.rs @@ -12,31 +12,35 @@ use std::collections::HashMap; pub enum Badge { #[serde(rename = "travis-ci")] TravisCi { - repository: String, branch: Option, + repository: String, + branch: Option, }, #[serde(rename = "appveyor")] Appveyor { - repository: String, branch: Option, service: Option, + repository: String, + branch: Option, + service: Option, }, #[serde(rename = "gitlab")] GitLab { - repository: String, branch: Option, - }, - #[serde(rename = "is-it-maintained-issue-resolution")] - IsItMaintainedIssueResolution { repository: String, + branch: Option, }, + #[serde(rename = "is-it-maintained-issue-resolution")] + IsItMaintainedIssueResolution { repository: String }, #[serde(rename = "is-it-maintained-open-issues")] - IsItMaintainedOpenIssues { - repository: String, - }, + IsItMaintainedOpenIssues { repository: String }, #[serde(rename = "codecov")] Codecov { - repository: String, branch: Option, service: Option, + repository: String, + branch: Option, + service: Option, }, #[serde(rename = "coveralls")] Coveralls { - repository: String, branch: Option, service: Option, + repository: String, + branch: Option, + service: Option, }, } @@ -51,8 +55,7 @@ impl Queryable for Badge { fn build((_, badge_type, attributes): Self::Row) -> Self { let json = json!({"badge_type": badge_type, "attributes": attributes}); - serde_json::from_value(json) - .expect("Invalid CI badge in the database") + serde_json::from_value(json).expect("Invalid CI badge in the database") } } @@ -63,20 +66,21 @@ impl Badge { pub fn badge_type(&self) -> &'static str { match *self { - Badge::TravisCi {..} => "travis-ci", - Badge::Appveyor {..} => "appveyor", - Badge::GitLab{..} => "gitlab", - Badge::IsItMaintainedIssueResolution{..} => "is-it-maintained-issue-resolution", - Badge::IsItMaintainedOpenIssues{..} => "is-it-maintained-open-issues", - Badge::Codecov{..} => "codecov", - Badge::Coveralls{..} => "coveralls", + Badge::TravisCi { .. } => "travis-ci", + Badge::Appveyor { .. } => "appveyor", + Badge::GitLab { .. } => "gitlab", + Badge::IsItMaintainedIssueResolution { .. } => "is-it-maintained-issue-resolution", + Badge::IsItMaintainedOpenIssues { .. } => "is-it-maintained-open-issues", + Badge::Codecov { .. } => "codecov", + Badge::Coveralls { .. } => "coveralls", } } - pub fn update_crate<'a>(conn: &PgConnection, - krate: &Crate, - badges: Option<&'a HashMap>>) - -> CargoResult> { + pub fn update_crate<'a>( + conn: &PgConnection, + krate: &Crate, + badges: Option<&'a HashMap>>, + ) -> CargoResult> { use diesel::{insert, delete}; #[derive(Insertable)] @@ -96,21 +100,26 @@ impl Badge { let json = json!({"badge_type": k, "attributes": attributes_json}); if serde_json::from_value::(json).is_ok() { - new_badges.push(NewBadge { - crate_id: krate.id, - badge_type: &**k, - attributes: attributes_json, - }); + new_badges.push( + NewBadge { + crate_id: krate.id, + badge_type: &**k, + attributes: attributes_json, + } + ); } else { invalid_badges.push(&**k); } } } - conn.transaction(|| { - delete(badges::table.filter(badges::crate_id.eq(krate.id))).execute(conn)?; - insert(&new_badges).into(badges::table).execute(conn)?; - Ok(invalid_badges) - }) + conn.transaction( + || { + delete(badges::table.filter(badges::crate_id.eq(krate.id))) + .execute(conn)?; + insert(&new_badges).into(badges::table).execute(conn)?; + Ok(invalid_badges) + } + ) } } diff --git a/src/bin/delete-crate.rs b/src/bin/delete-crate.rs index 3c15bc99204..00887fccc5d 100644 --- a/src/bin/delete-crate.rs +++ b/src/bin/delete-crate.rs @@ -30,80 +30,112 @@ fn main() { fn delete(tx: &postgres::transaction::Transaction) { let name = match env::args().nth(1) { - None => { println!("needs a crate-name argument"); return } + None => { + println!("needs a crate-name argument"); + return; + } Some(s) => s, }; let krate = Crate::find_by_name(tx, &name).unwrap(); - print!("Are you sure you want to delete {} ({}) [y/N]: ", name, krate.id); + print!( + "Are you sure you want to delete {} ({}) [y/N]: ", + name, + krate.id + ); io::stdout().flush().unwrap(); let mut line = String::new(); io::stdin().read_line(&mut line).unwrap(); - if !line.starts_with("y") { return } + if !line.starts_with("y") { + return; + } let versions = krate.versions(tx).unwrap(); for v in versions.iter() { println!("deleting version {} ({})", v.num, v.id); - let n = tx.execute("DELETE FROM version_downloads WHERE version_id = $1", - &[&v.id]).unwrap(); + let n = tx.execute( + "DELETE FROM version_downloads WHERE version_id = $1", + &[&v.id], + ) + .unwrap(); println!(" {} download records deleted", n); - let n = tx.execute("DELETE FROM version_authors WHERE version_id = $1", - &[&v.id]).unwrap(); + let n = tx.execute( + "DELETE FROM version_authors WHERE version_id = $1", + &[&v.id], + ) + .unwrap(); println!(" {} author records deleted", n); - let n = tx.execute("DELETE FROM dependencies WHERE version_id = $1", - &[&v.id]).unwrap(); + let n = tx.execute("DELETE FROM dependencies WHERE version_id = $1", &[&v.id]) + .unwrap(); println!(" {} dependencies deleted", n); - tx.execute("DELETE FROM versions WHERE id = $1", - &[&v.id]).unwrap(); + tx.execute("DELETE FROM versions WHERE id = $1", &[&v.id]) + .unwrap(); } println!("deleting follows"); - let n = tx.execute("DELETE FROM follows WHERE crate_id = $1", - &[&krate.id]).unwrap(); + let n = tx.execute("DELETE FROM follows WHERE crate_id = $1", &[&krate.id]) + .unwrap(); println!(" {} deleted", n); println!("deleting crate download records"); - let n = tx.execute("DELETE FROM crate_downloads WHERE crate_id = $1", - &[&krate.id]).unwrap(); + let n = tx.execute( + "DELETE FROM crate_downloads WHERE crate_id = $1", + &[&krate.id], + ) + .unwrap(); println!(" {} deleted", n); println!("deleting crate owners"); - let n = tx.execute("DELETE FROM crate_owners WHERE crate_id = $1", - &[&krate.id]).unwrap(); + let n = tx.execute("DELETE FROM crate_owners WHERE crate_id = $1", &[&krate.id]) + .unwrap(); println!(" {} deleted", n); println!("disabling reserved crate name trigger"); - let _ = tx.execute("ALTER TABLE crates DISABLE TRIGGER trigger_ensure_crate_name_not_reserved;", - &[]).unwrap(); + let _ = tx.execute( + "ALTER TABLE crates DISABLE TRIGGER trigger_ensure_crate_name_not_reserved;", + &[], + ) + .unwrap(); println!("deleting crate keyword connections"); - let n = tx.execute("DELETE FROM crates_keywords WHERE crate_id = $1", - &[&krate.id]).unwrap(); + let n = tx.execute( + "DELETE FROM crates_keywords WHERE crate_id = $1", + &[&krate.id], + ) + .unwrap(); println!(" {} deleted", n); println!("deleting crate category connections"); - let n = tx.execute("DELETE FROM crates_categories WHERE crate_id = $1", - &[&krate.id]).unwrap(); + let n = tx.execute( + "DELETE FROM crates_categories WHERE crate_id = $1", + &[&krate.id], + ) + .unwrap(); println!(" {} deleted", n); println!("enabling reserved crate name trigger"); - let _ = tx.execute("ALTER TABLE crates ENABLE TRIGGER trigger_ensure_crate_name_not_reserved;", - &[]).unwrap(); + let _ = tx.execute( + "ALTER TABLE crates ENABLE TRIGGER trigger_ensure_crate_name_not_reserved;", + &[], + ) + .unwrap(); println!("deleting crate badges"); - let n = tx.execute("DELETE FROM badges WHERE crate_id = $1", - &[&krate.id]).unwrap(); + let n = tx.execute("DELETE FROM badges WHERE crate_id = $1", &[&krate.id]) + .unwrap(); println!(" {} deleted", n); println!("deleting the crate"); - let n = tx.execute("DELETE FROM crates WHERE id = $1", - &[&krate.id]).unwrap(); + let n = tx.execute("DELETE FROM crates WHERE id = $1", &[&krate.id]) + .unwrap(); println!(" {} deleted", n); print!("commit? [y/N]: "); io::stdout().flush().unwrap(); let mut line = String::new(); io::stdin().read_line(&mut line).unwrap(); - if !line.starts_with("y") { panic!("aborting transaction"); } + if !line.starts_with("y") { + panic!("aborting transaction"); + } } diff --git a/src/bin/delete-version.rs b/src/bin/delete-version.rs index c3711175146..826cdc968d9 100644 --- a/src/bin/delete-version.rs +++ b/src/bin/delete-version.rs @@ -31,40 +31,62 @@ fn main() { fn delete(tx: &postgres::transaction::Transaction) { let name = match env::args().nth(1) { - None => { println!("needs a crate-name argument"); return } + None => { + println!("needs a crate-name argument"); + return; + } Some(s) => s, }; let version = match env::args().nth(2) { - None => { println!("needs a version argument"); return } + None => { + println!("needs a version argument"); + return; + } Some(s) => s, }; let version = semver::Version::parse(&version).unwrap(); let krate = Crate::find_by_name(tx, &name).unwrap(); - let v = Version::find_by_num(tx, krate.id, &version).unwrap().unwrap(); - print!("Are you sure you want to delete {}#{} ({}) [y/N]: ", name, version, - v.id); + let v = Version::find_by_num(tx, krate.id, &version) + .unwrap() + .unwrap(); + print!( + "Are you sure you want to delete {}#{} ({}) [y/N]: ", + name, + version, + v.id + ); io::stdout().flush().unwrap(); let mut line = String::new(); io::stdin().read_line(&mut line).unwrap(); - if !line.starts_with("y") { return } + if !line.starts_with("y") { + return; + } println!("deleting version {} ({})", v.num, v.id); - let n = tx.execute("DELETE FROM version_downloads WHERE version_id = $1", - &[&v.id]).unwrap(); + let n = tx.execute( + "DELETE FROM version_downloads WHERE version_id = $1", + &[&v.id], + ) + .unwrap(); println!(" {} download records deleted", n); - let n = tx.execute("DELETE FROM version_authors WHERE version_id = $1", - &[&v.id]).unwrap(); + let n = tx.execute( + "DELETE FROM version_authors WHERE version_id = $1", + &[&v.id], + ) + .unwrap(); println!(" {} author records deleted", n); - let n = tx.execute("DELETE FROM dependencies WHERE version_id = $1", - &[&v.id]).unwrap(); + let n = tx.execute("DELETE FROM dependencies WHERE version_id = $1", &[&v.id]) + .unwrap(); println!(" {} dependencies deleted", n); - tx.execute("DELETE FROM versions WHERE id = $1", - &[&v.id]).unwrap(); + tx.execute("DELETE FROM versions WHERE id = $1", &[&v.id]) + .unwrap(); print!("commit? [y/N]: "); io::stdout().flush().unwrap(); let mut line = String::new(); io::stdin().read_line(&mut line).unwrap(); - if !line.starts_with("y") { panic!("aborting transaction"); } + if !line.starts_with("y") { + panic!("aborting transaction"); + } } diff --git a/src/bin/fill-in-user-id.rs b/src/bin/fill-in-user-id.rs index e1dfae7442d..0e3a9dea724 100644 --- a/src/bin/fill-in-user-id.rs +++ b/src/bin/fill-in-user-id.rs @@ -53,13 +53,19 @@ struct GithubUser { fn update(app: &App, tx: &postgres::transaction::Transaction) { let query = "SELECT id, gh_login, gh_access_token, gh_avatar FROM users WHERE gh_id IS NULL"; - let rows = tx.query(query, &[]).unwrap().into_iter().map(|row| { - let id: i32 = row.get("id"); - let login: String = row.get("gh_login"); - let token: String = row.get("gh_access_token"); - let avatar: Option = row.get("gh_avatar"); - (id, login, http::token(token), avatar) - }).collect::>(); + let rows = tx.query(query, &[]) + .unwrap() + .into_iter() + .map( + |row| { + let id: i32 = row.get("id"); + let login: String = row.get("gh_login"); + let token: String = row.get("gh_access_token"); + let avatar: Option = row.get("gh_avatar"); + (id, login, http::token(token), avatar) + } + ) + .collect::>(); for (id, login, token, avatar) in rows { println!("attempt: {}/{}", id, login); @@ -69,12 +75,14 @@ fn update(app: &App, tx: &postgres::transaction::Transaction) { let ghuser: GithubUser = http::parse_github_response(handle, &resp)?; if let Some(ref avatar) = avatar { if !avatar.contains(&ghuser.id.to_string()) { - return Err(human(&format_args!("avatar: {}", avatar))) + return Err(human(&format_args!("avatar: {}", avatar))); } } if ghuser.login == login { - tx.execute("UPDATE users SET gh_id = $1 WHERE id = $2", - &[&ghuser.id, &id])?; + tx.execute( + "UPDATE users SET gh_id = $1 WHERE id = $2", + &[&ghuser.id, &id], + )?; Ok(()) } else { Err(human(&format_args!("different login: {}", ghuser.login))) @@ -85,4 +93,3 @@ fn update(app: &App, tx: &postgres::transaction::Transaction) { } } } - diff --git a/src/bin/populate.rs b/src/bin/populate.rs index b4567d6c367..84fe9a31d4e 100644 --- a/src/bin/populate.rs +++ b/src/bin/populate.rs @@ -27,9 +27,9 @@ fn main() { } fn update(tx: &postgres::transaction::Transaction) -> postgres::Result<()> { - let ids = env::args().skip(1).filter_map(|arg| { - arg.parse::().ok() - }); + let ids = env::args() + .skip(1) + .filter_map(|arg| arg.parse::().ok()); for id in ids { let now = time::now_utc().to_timespec(); let mut rng = StdRng::new().unwrap(); @@ -38,10 +38,12 @@ fn update(tx: &postgres::transaction::Transaction) -> postgres::Result<()> { for day in 0..90 { let moment = now + Duration::days(-day); dls += rng.gen_range(-100, 100); - tx.execute("INSERT INTO version_downloads \ + tx.execute( + "INSERT INTO version_downloads \ (version_id, downloads, date) \ VALUES ($1, $2, $3)", - &[&id, &dls, &moment])?; + &[&id, &dls, &moment], + )?; } } Ok(()) diff --git a/src/bin/server.rs b/src/bin/server.rs index daadf46a9f7..8cf6099e56b 100644 --- a/src/bin/server.rs +++ b/src/bin/server.rs @@ -31,8 +31,9 @@ fn main() { let mut opts = git2::FetchOptions::new(); opts.remote_callbacks(cb); git2::build::RepoBuilder::new() - .fetch_options(opts) - .clone(&url, &checkout).unwrap() + .fetch_options(opts) + .clone(&url, &checkout) + .unwrap() } }; let mut cfg = repo.config().unwrap(); @@ -57,42 +58,48 @@ fn main() { (Env::Production, Replica::Primary) => { // `env` panics if these vars are not set Uploader::S3 { - bucket: s3::Bucket::new(env("S3_BUCKET"), - env::var("S3_REGION").ok(), - env("S3_ACCESS_KEY"), - env("S3_SECRET_KEY"), - &api_protocol), + bucket: s3::Bucket::new( + env("S3_BUCKET"), + env::var("S3_REGION").ok(), + env("S3_ACCESS_KEY"), + env("S3_SECRET_KEY"), + &api_protocol, + ), proxy: None, } - }, + } (Env::Production, Replica::ReadOnlyMirror) => { // Read-only mirrors don't need access key or secret key, // but they might have them. Definitely need bucket though. Uploader::S3 { - bucket: s3::Bucket::new(env("S3_BUCKET"), - env::var("S3_REGION").ok(), - env::var("S3_ACCESS_KEY").unwrap_or(String::new()), - env::var("S3_SECRET_KEY").unwrap_or(String::new()), - &api_protocol), + bucket: s3::Bucket::new( + env("S3_BUCKET"), + env::var("S3_REGION").ok(), + env::var("S3_ACCESS_KEY").unwrap_or(String::new()), + env::var("S3_SECRET_KEY").unwrap_or(String::new()), + &api_protocol, + ), proxy: None, } - }, + } _ => { if env::var("S3_BUCKET").is_ok() { println!("Using S3 uploader"); Uploader::S3 { - bucket: s3::Bucket::new(env("S3_BUCKET"), - env::var("S3_REGION").ok(), - env::var("S3_ACCESS_KEY").unwrap_or(String::new()), - env::var("S3_SECRET_KEY").unwrap_or(String::new()), - &api_protocol), + bucket: s3::Bucket::new( + env("S3_BUCKET"), + env::var("S3_REGION").ok(), + env::var("S3_ACCESS_KEY").unwrap_or(String::new()), + env::var("S3_SECRET_KEY").unwrap_or(String::new()), + &api_protocol, + ), proxy: None, } } else { println!("Using local uploader, crate files will be in the dist directory"); Uploader::Local } - }, + } }; let config = cargo_registry::Config { @@ -115,9 +122,12 @@ fn main() { let port = if heroku { 8888 } else { - env::var("PORT").ok().and_then(|s| s.parse().ok()).unwrap_or(8888) + env::var("PORT") + .ok() + .and_then(|s| s.parse().ok()) + .unwrap_or(8888) }; - let threads = if cargo_env == Env::Development {1} else {50}; + let threads = if cargo_env == Env::Development { 1 } else { 50 }; let mut cfg = civet::Config::new(); cfg.port(port).threads(threads).keep_alive(true); let _a = Server::start(cfg, app); diff --git a/src/bin/transfer-crates.rs b/src/bin/transfer-crates.rs index 817a1943d3f..5f9a5393c15 100644 --- a/src/bin/transfer-crates.rs +++ b/src/bin/transfer-crates.rs @@ -31,11 +31,17 @@ fn main() { fn transfer(tx: &postgres::transaction::Transaction) { let from = match env::args().nth(1) { - None => { println!("needs a from-user argument"); return } + None => { + println!("needs a from-user argument"); + return; + } Some(s) => s, }; let to = match env::args().nth(2) { - None => { println!("needs a to-user argument"); return } + None => { + println!("needs a to-user argument"); + return; + } Some(s) => s, }; @@ -54,15 +60,20 @@ fn transfer(tx: &postgres::transaction::Transaction) { get_confirm("continue?"); } - println!("Are you sure you want to transfer crates from {} to {}", - from.gh_login, to.gh_login); + println!( + "Are you sure you want to transfer crates from {} to {}", + from.gh_login, + to.gh_login + ); get_confirm("continue"); - let stmt = tx.prepare("SELECT * FROM crate_owners + let stmt = tx.prepare( + "SELECT * FROM crate_owners WHERE owner_id = $1 - AND owner_kind = $2") - .unwrap(); + AND owner_kind = $2" + ) + .unwrap(); let rows = stmt.query(&[&from.id, &(OwnerKind::User as i32)]).unwrap(); for row in rows.iter() { let id: i32 = row.get("id"); @@ -72,9 +83,12 @@ fn transfer(tx: &postgres::transaction::Transaction) { if owners.len() != 1 { println!("warning: not exactly one owner for {}", krate.name); } - let n = tx.execute("UPDATE crate_owners SET owner_id = $1 + let n = tx.execute( + "UPDATE crate_owners SET owner_id = $1 WHERE id $2", - &[&to.id, &id]).unwrap(); + &[&to.id, &id], + ) + .unwrap(); assert_eq!(n, 1); } diff --git a/src/bin/update-downloads.rs b/src/bin/update-downloads.rs index 299d97558aa..67c64b91594 100644 --- a/src/bin/update-downloads.rs +++ b/src/bin/update-downloads.rs @@ -17,8 +17,7 @@ static LIMIT: i64 = 1000; #[allow(dead_code)] // dead in tests fn main() { - let daemon = env::args().nth(1).as_ref().map(|s| &s[..]) - == Some("daemon"); + let daemon = env::args().nth(1).as_ref().map(|s| &s[..]) == Some("daemon"); let sleep = env::args().nth(2).map(|s| s.parse().unwrap()); loop { let conn = cargo_registry::db::connect_now(); @@ -27,7 +26,7 @@ fn main() { if daemon { std::thread::sleep(Duration::new(sleep.unwrap(), 0)); } else { - break + break; } } } @@ -37,12 +36,15 @@ fn update(conn: &postgres::GenericConnection) -> postgres::Result<()> { loop { // FIXME(rust-lang/rust#27401): weird declaration to make sure this // variable gets dropped. - let tx; tx = conn.transaction()?; + let tx; + tx = conn.transaction()?; { - let stmt = tx.prepare("SELECT * FROM version_downloads \ + let stmt = tx.prepare( + "SELECT * FROM version_downloads \ WHERE processed = FALSE AND id > $1 ORDER BY id ASC - LIMIT $2")?; + LIMIT $2" + )?; let mut rows = stmt.query(&[&max, &LIMIT])?; match collect(&tx, &mut rows)? { None => break, @@ -55,8 +57,7 @@ fn update(conn: &postgres::GenericConnection) -> postgres::Result<()> { Ok(()) } -fn collect(tx: &postgres::transaction::Transaction, - rows: &mut postgres::rows::Rows) -> postgres::Result> { +fn collect(tx: &postgres::transaction::Transaction, rows: &mut postgres::rows::Rows) -> postgres::Result> { // Anything older than 24 hours ago will be frozen and will not be queried // against again. let now = chrono::UTC::now(); @@ -67,9 +68,13 @@ fn collect(tx: &postgres::transaction::Transaction, let download: VersionDownload = Model::from_row(&row); assert!(map.insert(download.id, download).is_none()); } - println!("updating {} versions (cutoff {})", map.len(), now.to_rfc2822()); + println!( + "updating {} versions (cutoff {})", + map.len(), + now.to_rfc2822() + ); if map.len() == 0 { - return Ok(None) + return Ok(None); } let mut max = 0; @@ -79,50 +84,63 @@ fn collect(tx: &postgres::transaction::Transaction, max = *id; } if download.date > cutoff && download.counted == download.downloads { - continue + continue; } let amt = download.downloads - download.counted; // Flag this row as having been processed if we're passed the cutoff, // and unconditionally increment the number of counted downloads. - tx.execute("UPDATE version_downloads + tx.execute( + "UPDATE version_downloads SET processed = $2, counted = counted + $3 WHERE id = $1", - &[id, &(download.date < cutoff), &amt])?; + &[id, &(download.date < cutoff), &amt], + )?; total += amt as i64; if amt == 0 { - continue + continue; } let crate_id = Version::find(tx, download.version_id).unwrap().crate_id; // Update the total number of version downloads - tx.execute("UPDATE versions + tx.execute( + "UPDATE versions SET downloads = downloads + $1 WHERE id = $2", - &[&amt, &download.version_id])?; + &[&amt, &download.version_id], + )?; // Update the total number of crate downloads - tx.execute("UPDATE crates SET downloads = downloads + $1 - WHERE id = $2", &[&amt, &crate_id])?; + tx.execute( + "UPDATE crates SET downloads = downloads + $1 + WHERE id = $2", + &[&amt, &crate_id], + )?; // Update the total number of crate downloads for today - let cnt = tx.execute("UPDATE crate_downloads + let cnt = tx.execute( + "UPDATE crate_downloads SET downloads = downloads + $2 WHERE crate_id = $1 AND date = $3", - &[&crate_id, &amt, &download.date])?; + &[&crate_id, &amt, &download.date], + )?; if cnt == 0 { - tx.execute("INSERT INTO crate_downloads + tx.execute( + "INSERT INTO crate_downloads (crate_id, downloads, date) VALUES ($1, $2, $3)", - &[&crate_id, &amt, &download.date])?; + &[&crate_id, &amt, &download.date], + )?; } } // After everything else is done, update the global counter of total // downloads. - tx.execute("UPDATE metadata SET total_downloads = total_downloads + $1", - &[&total])?; + tx.execute( + "UPDATE metadata SET total_downloads = total_downloads + $1", + &[&total], + )?; Ok(Some(max)) } @@ -140,20 +158,25 @@ mod test { use cargo_registry::{Version, Crate, User, Model, env}; fn conn() -> postgres::Connection { - postgres::Connection::connect(&env("TEST_DATABASE_URL")[..], - postgres::TlsMode::None).unwrap() + postgres::Connection::connect(&env("TEST_DATABASE_URL")[..], postgres::TlsMode::None).unwrap() } - fn user(conn: &postgres::transaction::Transaction) -> User{ - User::find_or_insert(conn, 2, "login", None, None, None, - "access_token").unwrap() + fn user(conn: &postgres::transaction::Transaction) -> User { + User::find_or_insert(conn, 2, "login", None, None, None, "access_token").unwrap() } fn crate_downloads(tx: &postgres::transaction::Transaction, id: i32, expected: usize) { - let stmt = tx.prepare("SELECT * FROM crate_downloads - WHERE crate_id = $1").unwrap(); - let dl: i32 = stmt.query(&[&id]).unwrap().iter() - .next().unwrap().get("downloads"); + let stmt = tx.prepare( + "SELECT * FROM crate_downloads + WHERE crate_id = $1" + ) + .unwrap(); + let dl: i32 = stmt.query(&[&id]) + .unwrap() + .iter() + .next() + .unwrap() + .get("downloads"); assert_eq!(dl, expected as i32); } @@ -162,20 +185,42 @@ mod test { let conn = conn(); let tx = conn.transaction().unwrap(); let user = user(&tx); - let krate = Crate::find_or_insert(&tx, "foo", user.id, &None, &None, - &None, &None, &None, &None, - &None, None).unwrap(); - let version = Version::insert(&tx, krate.id, - &semver::Version::parse("1.0.0").unwrap(), - &HashMap::new(), &[]).unwrap(); - tx.execute("INSERT INTO version_downloads \ + let krate = Crate::find_or_insert( + &tx, + "foo", + user.id, + &None, + &None, + &None, + &None, + &None, + &None, + &None, + None, + ) + .unwrap(); + let version = Version::insert( + &tx, + krate.id, + &semver::Version::parse("1.0.0").unwrap(), + &HashMap::new(), + &[], + ) + .unwrap(); + tx.execute( + "INSERT INTO version_downloads \ (version_id) VALUES ($1)", - &[&version.id]).unwrap(); - tx.execute("INSERT INTO version_downloads \ + &[&version.id], + ) + .unwrap(); + tx.execute( + "INSERT INTO version_downloads \ (version_id, date, processed) VALUES ($1, current_date - interval '1 day', true)", - &[&version.id]).unwrap(); + &[&version.id], + ) + .unwrap(); ::update(&tx).unwrap(); assert_eq!(Version::find(&tx, version.id).unwrap().downloads, 1); assert_eq!(Crate::find(&tx, krate.id).unwrap().downloads, 1); @@ -189,21 +234,47 @@ mod test { let conn = conn(); let tx = conn.transaction().unwrap(); let user = user(&tx); - let krate = Crate::find_or_insert(&tx, "foo", user.id, &None, - &None, &None, &None, &None, - &None, &None, None).unwrap(); - let version = Version::insert(&tx, krate.id, - &semver::Version::parse("1.0.0").unwrap(), - &HashMap::new(), &[]).unwrap(); - tx.execute("INSERT INTO version_downloads \ + let krate = Crate::find_or_insert( + &tx, + "foo", + user.id, + &None, + &None, + &None, + &None, + &None, + &None, + &None, + None, + ) + .unwrap(); + let version = Version::insert( + &tx, + krate.id, + &semver::Version::parse("1.0.0").unwrap(), + &HashMap::new(), + &[], + ) + .unwrap(); + tx.execute( + "INSERT INTO version_downloads \ (version_id, downloads, counted, date, processed) VALUES ($1, 2, 2, current_date - interval '2 days', false)", - &[&version.id]).unwrap(); + &[&version.id], + ) + .unwrap(); ::update(&tx).unwrap(); - let stmt = tx.prepare("SELECT processed FROM version_downloads - WHERE version_id = $1").unwrap(); - let processed: bool = stmt.query(&[&version.id]).unwrap().iter() - .next().unwrap().get("processed"); + let stmt = tx.prepare( + "SELECT processed FROM version_downloads + WHERE version_id = $1" + ) + .unwrap(); + let processed: bool = stmt.query(&[&version.id]) + .unwrap() + .iter() + .next() + .unwrap() + .get("processed"); assert!(processed); } @@ -212,22 +283,48 @@ mod test { let conn = conn(); let tx = conn.transaction().unwrap(); let user = user(&tx); - let krate = Crate::find_or_insert(&tx, "foo", user.id, &None, - &None, &None, &None, &None, - &None, &None, None).unwrap(); - let version = Version::insert(&tx, krate.id, - &semver::Version::parse("1.0.0").unwrap(), - &HashMap::new(), &[]).unwrap(); + let krate = Crate::find_or_insert( + &tx, + "foo", + user.id, + &None, + &None, + &None, + &None, + &None, + &None, + &None, + None, + ) + .unwrap(); + let version = Version::insert( + &tx, + krate.id, + &semver::Version::parse("1.0.0").unwrap(), + &HashMap::new(), + &[], + ) + .unwrap(); let time = time::now_utc().to_timespec() - Duration::hours(2); - tx.execute("INSERT INTO version_downloads \ + tx.execute( + "INSERT INTO version_downloads \ (version_id, downloads, counted, date, processed) VALUES ($1, 2, 2, date($2), false)", - &[&version.id, &time]).unwrap(); + &[&version.id, &time], + ) + .unwrap(); ::update(&tx).unwrap(); - let stmt = tx.prepare("SELECT processed FROM version_downloads - WHERE version_id = $1").unwrap(); - let processed: bool = stmt.query(&[&version.id]).unwrap().iter() - .next().unwrap().get("processed"); + let stmt = tx.prepare( + "SELECT processed FROM version_downloads + WHERE version_id = $1" + ) + .unwrap(); + let processed: bool = stmt.query(&[&version.id]) + .unwrap() + .iter() + .next() + .unwrap() + .get("processed"); assert!(!processed); } @@ -236,26 +333,54 @@ mod test { let conn = conn(); let tx = conn.transaction().unwrap(); let user = user(&tx); - let krate = Crate::find_or_insert(&tx, "foo", user.id, &None, - &None, &None, &None, &None, - &None, &None, None).unwrap(); - let version = Version::insert(&tx, krate.id, - &semver::Version::parse("1.0.0").unwrap(), - &HashMap::new(), &[]).unwrap(); - tx.execute("UPDATE versions + let krate = Crate::find_or_insert( + &tx, + "foo", + user.id, + &None, + &None, + &None, + &None, + &None, + &None, + &None, + None, + ) + .unwrap(); + let version = Version::insert( + &tx, + krate.id, + &semver::Version::parse("1.0.0").unwrap(), + &HashMap::new(), + &[], + ) + .unwrap(); + tx.execute( + "UPDATE versions SET updated_at = current_date - interval '2 hours'", - &[]).unwrap(); - tx.execute("UPDATE crates + &[], + ) + .unwrap(); + tx.execute( + "UPDATE crates SET updated_at = current_date - interval '2 hours'", - &[]).unwrap(); - tx.execute("INSERT INTO version_downloads \ + &[], + ) + .unwrap(); + tx.execute( + "INSERT INTO version_downloads \ (version_id, downloads, counted, date, processed) VALUES ($1, 2, 1, current_date, false)", - &[&version.id]).unwrap(); - tx.execute("INSERT INTO version_downloads \ + &[&version.id], + ) + .unwrap(); + tx.execute( + "INSERT INTO version_downloads \ (version_id, date) VALUES ($1, current_date - interval '1 day')", - &[&version.id]).unwrap(); + &[&version.id], + ) + .unwrap(); let version_before = Version::find(&tx, version.id).unwrap(); let krate_before = Crate::find(&tx, krate.id).unwrap(); @@ -276,22 +401,47 @@ mod test { let conn = conn(); let tx = conn.transaction().unwrap(); let user = user(&tx); - let krate = Crate::find_or_insert(&tx, "foo", user.id, &None, - &None, &None, &None, &None, - &None, &None, None).unwrap(); - let version = Version::insert(&tx, krate.id, - &semver::Version::parse("1.0.0").unwrap(), - &HashMap::new(), &[]).unwrap(); - tx.execute("UPDATE versions + let krate = Crate::find_or_insert( + &tx, + "foo", + user.id, + &None, + &None, + &None, + &None, + &None, + &None, + &None, + None, + ) + .unwrap(); + let version = Version::insert( + &tx, + krate.id, + &semver::Version::parse("1.0.0").unwrap(), + &HashMap::new(), + &[], + ) + .unwrap(); + tx.execute( + "UPDATE versions SET updated_at = current_date - interval '2 days'", - &[]).unwrap(); - tx.execute("UPDATE crates + &[], + ) + .unwrap(); + tx.execute( + "UPDATE crates SET updated_at = current_date - interval '2 days'", - &[]).unwrap(); - tx.execute("INSERT INTO version_downloads \ + &[], + ) + .unwrap(); + tx.execute( + "INSERT INTO version_downloads \ (version_id, downloads, counted, date, processed) VALUES ($1, 2, 2, current_date - interval '2 days', false)", - &[&version.id]).unwrap(); + &[&version.id], + ) + .unwrap(); let version_before = Version::find(&tx, version.id).unwrap(); let krate_before = Crate::find(&tx, krate.id).unwrap(); diff --git a/src/categories.rs b/src/categories.rs index 6cb41b05669..32abee2956e 100644 --- a/src/categories.rs +++ b/src/categories.rs @@ -13,8 +13,7 @@ struct Category { } impl Category { - fn from_parent(slug: &str, name: &str, description: &str, parent: Option<&Category>) - -> Category { + fn from_parent(slug: &str, name: &str, description: &str, parent: Option<&Category>) -> Category { match parent { Some(parent) => { Category { @@ -37,24 +36,20 @@ impl Category { fn required_string_from_toml<'a>(toml: &'a toml::Table, key: &str) -> CargoResult<&'a str> { toml.get(key) .and_then(toml::Value::as_str) - .chain_error(|| { - internal(&format_args!("Expected category TOML attribute '{}' to be a String", key)) - }) + .chain_error(|| internal(&format_args!("Expected category TOML attribute '{}' to be a String", key))) } fn optional_string_from_toml<'a>(toml: &'a toml::Table, key: &str) -> &'a str { - toml.get(key) - .and_then(toml::Value::as_str) - .unwrap_or("") + toml.get(key).and_then(toml::Value::as_str).unwrap_or("") } fn categories_from_toml(categories: &toml::Table, parent: Option<&Category>) -> CargoResult> { let mut result = vec![]; for (slug, details) in categories { - let details = details.as_table().chain_error(|| { - internal(&format_args!("category {} was not a TOML table", slug)) - })?; + let details = details + .as_table() + .chain_error(|| internal(&format_args!("category {} was not a TOML table", slug)))?; let category = Category::from_parent( slug, @@ -64,13 +59,11 @@ fn categories_from_toml(categories: &toml::Table, parent: Option<&Category>) -> ); if let Some(categories) = details.get("categories") { - let categories = categories.as_table().chain_error(|| { - internal(&format_args!("child categories of {} were not a table", slug)) - })?; + let categories = categories + .as_table() + .chain_error(|| internal(&format_args!("child categories of {} were not a table", slug)))?; - result.extend( - categories_from_toml(categories, Some(&category))? - ); + result.extend(categories_from_toml(categories, Some(&category))?); } result.push(category) @@ -84,35 +77,37 @@ pub fn sync() -> CargoResult<()> { let tx = conn.transaction().unwrap(); let categories = include_str!("./categories.toml"); - let toml = toml::Parser::new(categories).parse().expect( - "Could not parse categories.toml" - ); + let toml = toml::Parser::new(categories) + .parse() + .expect("Could not parse categories.toml"); - let categories = categories_from_toml(&toml, None).expect( - "Could not convert categories from TOML" - ); + let categories = categories_from_toml(&toml, None).expect("Could not convert categories from TOML"); for category in &categories { - tx.execute("\ + tx.execute( + "\ INSERT INTO categories (slug, category, description) \ VALUES (LOWER($1), $2, $3) \ ON CONFLICT (slug) DO UPDATE \ SET category = EXCLUDED.category, \ description = EXCLUDED.description;", - &[&category.slug, &category.name, &category.description] - )?; + &[&category.slug, &category.name, &category.description], + )?; } - let in_clause = categories.iter().map(|category| { - format!("LOWER('{}')", category.slug) - }).collect::>().join(","); + let in_clause = categories + .iter() + .map(|category| format!("LOWER('{}')", category.slug)) + .collect::>() + .join(","); - tx.execute(&format!("\ + tx.execute( + &format!("\ DELETE FROM categories \ WHERE slug NOT IN ({});", in_clause), - &[] - )?; + &[], + )?; tx.set_commit(); tx.finish().unwrap(); Ok(()) diff --git a/src/category.rs b/src/category.rs index f6f45cb2188..9f5d63f9fff 100644 --- a/src/category.rs +++ b/src/category.rs @@ -57,29 +57,38 @@ pub struct EncodableCategoryWithSubcategories { } impl Category { - pub fn find_by_category(conn: &GenericConnection, name: &str) - -> CargoResult { - let stmt = conn.prepare("SELECT * FROM categories \ - WHERE category = $1")?; + pub fn find_by_category(conn: &GenericConnection, name: &str) -> CargoResult { + let stmt = conn.prepare( + "SELECT * FROM categories \ + WHERE category = $1" + )?; let rows = stmt.query(&[&name])?; - rows.iter().next() - .chain_error(|| NotFound) - .map(|row| Model::from_row(&row)) + rows.iter() + .next() + .chain_error(|| NotFound) + .map(|row| Model::from_row(&row)) } - pub fn find_by_slug(conn: &GenericConnection, slug: &str) - -> CargoResult { - let stmt = conn.prepare("SELECT * FROM categories \ - WHERE slug = LOWER($1)")?; + pub fn find_by_slug(conn: &GenericConnection, slug: &str) -> CargoResult { + let stmt = conn.prepare( + "SELECT * FROM categories \ + WHERE slug = LOWER($1)" + )?; let rows = stmt.query(&[&slug])?; - rows.iter().next() - .chain_error(|| NotFound) - .map(|row| Model::from_row(&row)) + rows.iter() + .next() + .chain_error(|| NotFound) + .map(|row| Model::from_row(&row)) } pub fn encodable(self) -> EncodableCategory { let Category { - crates_cnt, category, slug, description, created_at, .. + crates_cnt, + category, + slug, + description, + created_at, + .. } = self; EncodableCategory { id: slug.clone(), @@ -91,78 +100,92 @@ impl Category { } } - pub fn update_crate<'a>(conn: &PgConnection, - krate: &Crate, - slugs: &[&'a str]) -> QueryResult> { + pub fn update_crate<'a>(conn: &PgConnection, krate: &Crate, slugs: &[&'a str]) -> QueryResult> { use diesel::expression::dsl::any; - conn.transaction(|| { - let categories = categories::table - .filter(categories::slug.eq(any(slugs))) - .load::(conn)?; - let invalid_categories = slugs.iter().cloned() - .filter(|s| !categories.iter().any(|c| c.slug == *s)) - .collect(); - let crate_categories = categories.iter() - .map(|c| CrateCategory { category_id: c.id, crate_id: krate.id }) - .collect::>(); - - delete(CrateCategory::belonging_to(krate)).execute(conn)?; - insert(&crate_categories).into(crates_categories::table).execute(conn)?; - Ok(invalid_categories) - }) + conn.transaction( + || { + let categories = categories::table + .filter(categories::slug.eq(any(slugs))) + .load::(conn)?; + let invalid_categories = slugs + .iter() + .cloned() + .filter(|s| !categories.iter().any(|c| c.slug == *s)) + .collect(); + let crate_categories = categories + .iter() + .map( + |c| { + CrateCategory { + category_id: c.id, + crate_id: krate.id, + } + } + ) + .collect::>(); + + delete(CrateCategory::belonging_to(krate)).execute(conn)?; + insert(&crate_categories) + .into(crates_categories::table) + .execute(conn)?; + Ok(invalid_categories) + } + ) } - pub fn update_crate_old(conn: &GenericConnection, - krate: &Crate, - categories: &[String]) -> CargoResult> { + pub fn update_crate_old(conn: &GenericConnection, krate: &Crate, categories: &[String]) -> CargoResult> { let old_categories = krate.categories(conn)?; - let old_categories_ids: HashSet<_> = old_categories.iter().map(|cat| { - cat.id - }).collect(); + let old_categories_ids: HashSet<_> = old_categories.iter().map(|cat| cat.id).collect(); // If a new category specified is not in the database, filter // it out and don't add it. Return it to be able to warn about it. let mut invalid_categories = vec![]; - let new_categories: Vec = categories.iter().flat_map(|c| { - match Category::find_by_slug(conn, c) { - Ok(cat) => Some(cat), - Err(_) => { - invalid_categories.push(c.to_string()); - None - }, - } - }).collect(); + let new_categories: Vec = categories + .iter() + .flat_map( + |c| match Category::find_by_slug(conn, c) { + Ok(cat) => Some(cat), + Err(_) => { + invalid_categories.push(c.to_string()); + None + } + } + ) + .collect(); - let new_categories_ids: HashSet<_> = new_categories.iter().map(|cat| { - cat.id - }).collect(); + let new_categories_ids: HashSet<_> = new_categories.iter().map(|cat| cat.id).collect(); let to_rm: Vec<_> = old_categories_ids - .difference(&new_categories_ids) - .cloned() - .collect(); + .difference(&new_categories_ids) + .cloned() + .collect(); let to_add: Vec<_> = new_categories_ids - .difference(&old_categories_ids) - .cloned() - .collect(); + .difference(&old_categories_ids) + .cloned() + .collect(); if !to_rm.is_empty() { - conn.execute("DELETE FROM crates_categories \ + conn.execute( + "DELETE FROM crates_categories \ WHERE category_id = ANY($1) \ AND crate_id = $2", - &[&to_rm, &krate.id])?; + &[&to_rm, &krate.id], + )?; } if !to_add.is_empty() { - let insert: Vec<_> = to_add.into_iter().map(|id| { - format!("({}, {})", krate.id, id) - }).collect(); + let insert: Vec<_> = to_add + .into_iter() + .map(|id| format!("({}, {})", krate.id, id)) + .collect(); let insert = insert.join(", "); - conn.execute(&format!("INSERT INTO crates_categories \ + conn.execute( + &format!("INSERT INTO crates_categories \ (crate_id, category_id) VALUES {}", insert), - &[])?; + &[], + )?; } Ok(invalid_categories) @@ -180,10 +203,7 @@ impl Category { Ok(rows.iter().next().unwrap().get("count")) } - pub fn toplevel(conn: &PgConnection, - sort: &str, - limit: i64, - offset: i64) -> QueryResult> { + pub fn toplevel(conn: &PgConnection, sort: &str, limit: i64, offset: i64) -> QueryResult> { use diesel::select; use diesel::expression::dsl::*; @@ -194,7 +214,9 @@ impl Category { // Collect all the top-level categories and sum up the crates_cnt of // the crates in all subcategories - select(sql::(&format!( + select( + sql::( + &format!( "c.id, c.category, c.slug, c.description, sum(c2.crates_cnt)::int as crates_cnt, c.created_at FROM categories as c @@ -203,13 +225,13 @@ impl Category { GROUP BY c.id {} LIMIT {} OFFSET {}", sort_sql, limit, offset - ))).load(conn) + ) + ) + ) + .load(conn) } - pub fn toplevel_old(conn: &GenericConnection, - sort: &str, - limit: i64, - offset: i64) -> CargoResult> { + pub fn toplevel_old(conn: &GenericConnection, sort: &str, limit: i64, offset: i64) -> CargoResult> { let sort_sql = match sort { "crates" => "ORDER BY crates_cnt DESC", @@ -218,7 +240,8 @@ impl Category { // Collect all the top-level categories and sum up the crates_cnt of // the crates in all subcategories - let stmt = conn.prepare(&format!( + let stmt = conn.prepare( + &format!( "SELECT c.id, c.category, c.slug, c.description, c.created_at, sum(c2.crates_cnt)::int as crates_cnt FROM categories as c @@ -227,7 +250,8 @@ impl Category { GROUP BY c.id {} LIMIT $1 OFFSET $2", sort_sql - ))?; + ) + )?; let categories: Vec<_> = stmt.query(&[&limit, &offset])? .iter() @@ -237,9 +261,9 @@ impl Category { Ok(categories) } - pub fn subcategories(&self, conn: &GenericConnection) - -> CargoResult> { - let stmt = conn.prepare("\ + pub fn subcategories(&self, conn: &GenericConnection) -> CargoResult> { + let stmt = conn.prepare( + "\ SELECT c.id, c.category, c.slug, c.description, c.created_at, \ COALESCE (( \ SELECT sum(c2.crates_cnt)::int \ @@ -249,7 +273,8 @@ impl Category { ), 0) as crates_cnt \ FROM categories as c \ WHERE c.category ILIKE $1 || '::%' \ - AND c.category NOT ILIKE $1 || '::%::%'")?; + AND c.category NOT ILIKE $1 || '::%::%'" + )?; let rows = stmt.query(&[&self.category])?; Ok(rows.iter().map(|r| Model::from_row(&r)).collect()) @@ -277,8 +302,7 @@ impl<'a> NewCategory<'a> { return Ok(c); } - categories.filter(slug.eq(self.slug)) - .first(conn) + categories.filter(slug.eq(self.slug)).first(conn) } } @@ -293,7 +317,9 @@ impl Model for Category { description: row.get("description"), } } - fn table_name(_: Option) -> &'static str { "categories" } + fn table_name(_: Option) -> &'static str { + "categories" + } } /// Handles the `GET /categories` route. @@ -310,14 +336,23 @@ pub fn index(req: &mut Request) -> CargoResult { let total = Category::count_toplevel(conn)?; #[derive(RustcEncodable)] - struct R { categories: Vec, meta: Meta } + struct R { + categories: Vec, + meta: Meta, + } #[derive(RustcEncodable)] - struct Meta { total: i64 } + struct Meta { + total: i64, + } - Ok(req.json(&R { - categories: categories, - meta: Meta { total: total }, - })) + Ok( + req.json( + &R { + categories: categories, + meta: Meta { total: total }, + } + ) + ) } /// Handles the `GET /categories/:category_id` route. @@ -325,9 +360,10 @@ pub fn show(req: &mut Request) -> CargoResult { let slug = &req.params()["category_id"]; let conn = req.tx()?; let cat = Category::find_by_slug(conn, slug)?; - let subcats = cat.subcategories(conn)?.into_iter().map(|s| { - s.encodable() - }).collect(); + let subcats = cat.subcategories(conn)? + .into_iter() + .map(|s| s.encodable()) + .collect(); let cat = cat.encodable(); let cat_with_subcats = EncodableCategoryWithSubcategories { id: cat.id, @@ -340,27 +376,43 @@ pub fn show(req: &mut Request) -> CargoResult { }; #[derive(RustcEncodable)] - struct R { category: EncodableCategoryWithSubcategories} + struct R { + category: EncodableCategoryWithSubcategories, + } Ok(req.json(&R { category: cat_with_subcats })) } /// Handles the `GET /category_slugs` route. pub fn slugs(req: &mut Request) -> CargoResult { let conn = req.tx()?; - let stmt = conn.prepare("SELECT slug FROM categories \ - ORDER BY slug")?; + let stmt = conn.prepare( + "SELECT slug FROM categories \ + ORDER BY slug" + )?; let rows = stmt.query(&[])?; #[derive(RustcEncodable)] - struct Slug { id: String, slug: String } + struct Slug { + id: String, + slug: String, + } - let slugs: Vec = rows.iter().map(|r| { - let slug: String = r.get("slug"); - Slug { id: slug.clone(), slug: slug } - }).collect(); + let slugs: Vec = rows.iter() + .map( + |r| { + let slug: String = r.get("slug"); + Slug { + id: slug.clone(), + slug: slug, + } + } + ) + .collect(); #[derive(RustcEncodable)] - struct R { category_slugs: Vec } + struct R { + category_slugs: Vec, + } Ok(req.json(&R { category_slugs: slugs })) } @@ -373,23 +425,29 @@ mod tests { fn pg_connection() -> PgConnection { let _ = dotenv(); - let database_url = env::var("TEST_DATABASE_URL") - .expect("TEST_DATABASE_URL must be set to run tests"); + let database_url = env::var("TEST_DATABASE_URL").expect("TEST_DATABASE_URL must be set to run tests"); let conn = PgConnection::establish(&database_url).unwrap(); // These tests deadlock if run concurrently - conn.batch_execute("BEGIN; LOCK categories IN ACCESS EXCLUSIVE MODE").unwrap(); + conn.batch_execute("BEGIN; LOCK categories IN ACCESS EXCLUSIVE MODE") + .unwrap(); conn } #[test] fn category_toplevel_excludes_subcategories() { let conn = pg_connection(); - conn.batch_execute("INSERT INTO categories (category, slug) VALUES + conn.batch_execute( + "INSERT INTO categories (category, slug) VALUES ('Cat 2', 'cat2'), ('Cat 1', 'cat1'), ('Cat 1::sub', 'cat1::sub') - ").unwrap(); - - let categories = Category::toplevel(&conn, "", 10, 0).unwrap() - .into_iter().map(|c| c.category).collect::>(); + " + ) + .unwrap(); + + let categories = Category::toplevel(&conn, "", 10, 0) + .unwrap() + .into_iter() + .map(|c| c.category) + .collect::>(); let expected = vec!["Cat 1".to_string(), "Cat 2".to_string()]; assert_eq!(expected, categories); } @@ -397,12 +455,18 @@ mod tests { #[test] fn category_toplevel_orders_by_crates_cnt_when_sort_given() { let conn = pg_connection(); - conn.batch_execute("INSERT INTO categories (category, slug, crates_cnt) VALUES + conn.batch_execute( + "INSERT INTO categories (category, slug, crates_cnt) VALUES ('Cat 1', 'cat1', 0), ('Cat 2', 'cat2', 2), ('Cat 3', 'cat3', 1) - ").unwrap(); - - let categories = Category::toplevel(&conn, "crates", 10, 0).unwrap() - .into_iter().map(|c| c.category).collect::>(); + " + ) + .unwrap(); + + let categories = Category::toplevel(&conn, "crates", 10, 0) + .unwrap() + .into_iter() + .map(|c| c.category) + .collect::>(); let expected = vec!["Cat 2".to_string(), "Cat 3".to_string(), "Cat 1".to_string()]; assert_eq!(expected, categories); } @@ -410,17 +474,26 @@ mod tests { #[test] fn category_toplevel_applies_limit_and_offset() { let conn = pg_connection(); - conn.batch_execute("INSERT INTO categories (category, slug) VALUES + conn.batch_execute( + "INSERT INTO categories (category, slug) VALUES ('Cat 1', 'cat1'), ('Cat 2', 'cat2') - ").unwrap(); - - let categories = Category::toplevel(&conn, "", 1, 0).unwrap() - .into_iter().map(|c| c.category).collect::>(); + " + ) + .unwrap(); + + let categories = Category::toplevel(&conn, "", 1, 0) + .unwrap() + .into_iter() + .map(|c| c.category) + .collect::>(); let expected = vec!["Cat 1".to_string()]; assert_eq!(expected, categories); - let categories = Category::toplevel(&conn, "", 1, 1).unwrap() - .into_iter().map(|c| c.category).collect::>(); + let categories = Category::toplevel(&conn, "", 1, 1) + .unwrap() + .into_iter() + .map(|c| c.category) + .collect::>(); let expected = vec!["Cat 2".to_string()]; assert_eq!(expected, categories); } @@ -428,14 +501,20 @@ mod tests { #[test] fn category_toplevel_includes_subcategories_in_crate_cnt() { let conn = pg_connection(); - conn.batch_execute("INSERT INTO categories (category, slug, crates_cnt) VALUES + conn.batch_execute( + "INSERT INTO categories (category, slug, crates_cnt) VALUES ('Cat 1', 'cat1', 1), ('Cat 1::sub', 'cat1::sub', 2), ('Cat 2', 'cat2', 3), ('Cat 2::Sub 1', 'cat2::sub1', 4), ('Cat 2::Sub 2', 'cat2::sub2', 5), ('Cat 3', 'cat3', 6) - ").unwrap(); - - let categories = Category::toplevel(&conn, "crates", 10, 0).unwrap() - .into_iter().map(|c| (c.category, c.crates_cnt)).collect::>(); + " + ) + .unwrap(); + + let categories = Category::toplevel(&conn, "crates", 10, 0) + .unwrap() + .into_iter() + .map(|c| (c.category, c.crates_cnt)) + .collect::>(); let expected = vec![ ("Cat 2".to_string(), 12), ("Cat 3".to_string(), 6), @@ -447,22 +526,31 @@ mod tests { #[test] fn category_toplevel_applies_limit_and_offset_after_grouping() { let conn = pg_connection(); - conn.batch_execute("INSERT INTO categories (category, slug, crates_cnt) VALUES + conn.batch_execute( + "INSERT INTO categories (category, slug, crates_cnt) VALUES ('Cat 1', 'cat1', 1), ('Cat 1::sub', 'cat1::sub', 2), ('Cat 2', 'cat2', 3), ('Cat 2::Sub 1', 'cat2::sub1', 4), ('Cat 2::Sub 2', 'cat2::sub2', 5), ('Cat 3', 'cat3', 6) - ").unwrap(); - - let categories = Category::toplevel(&conn, "crates", 2, 0).unwrap() - .into_iter().map(|c| (c.category, c.crates_cnt)).collect::>(); + " + ) + .unwrap(); + + let categories = Category::toplevel(&conn, "crates", 2, 0) + .unwrap() + .into_iter() + .map(|c| (c.category, c.crates_cnt)) + .collect::>(); let expected = vec![ ("Cat 2".to_string(), 12), ("Cat 3".to_string(), 6), ]; assert_eq!(expected, categories); - let categories = Category::toplevel(&conn, "crates", 2, 1).unwrap() - .into_iter().map(|c| (c.category, c.crates_cnt)).collect::>(); + let categories = Category::toplevel(&conn, "crates", 2, 1) + .unwrap() + .into_iter() + .map(|c| (c.category, c.crates_cnt)) + .collect::>(); let expected = vec![ ("Cat 3".to_string(), 6), ("Cat 1".to_string(), 3), diff --git a/src/db.rs b/src/db.rs index 68a39c5a9c4..0e697ffdb31 100644 --- a/src/db.rs +++ b/src/db.rs @@ -59,11 +59,9 @@ pub fn tls_handshake() -> Box { // better solution in the future for certificate verification... impl TlsHandshake for MyHandshake { - fn tls_handshake(&self, - _domain: &str, - stream: Stream) - -> Result, Box> { - let stream = self.0.danger_connect_without_providing_domain_for_certificate_verification_and_server_name_indication(stream)?; + fn tls_handshake(&self, _domain: &str, stream: Stream) -> Result, Box> { + let stream = self.0 + .danger_connect_without_providing_domain_for_certificate_verification_and_server_name_indication(stream)?; Ok(Box::new(stream)) } } @@ -75,8 +73,7 @@ pub fn tls_handshake() -> Box { } let mut builder = SslConnectorBuilder::new(SslMethod::tls()).unwrap(); - builder.builder_mut() - .set_verify(SSL_VERIFY_NONE); + builder.builder_mut().set_verify(SSL_VERIFY_NONE); Box::new(MyHandshake(builder.build())) } @@ -145,9 +142,10 @@ impl Transaction { pub fn conn(&self) -> CargoResult<&r2d2::PooledConnection> { if !self.slot.filled() { - let conn = self.app.database.get().map_err(|e| { - internal(&format_args!("failed to get a database connection: {}", e)) - })?; + let conn = self.app + .database + .get() + .map_err(|e| internal(&format_args!("failed to get a database connection: {}", e)))?; self.slot.fill(Box::new(conn)); } Ok(&**self.slot.borrow().unwrap()) @@ -183,23 +181,23 @@ impl Transaction { } impl Middleware for TransactionMiddleware { - fn before(&self, req: &mut Request) -> Result<(), Box> { + fn before(&self, req: &mut Request) -> Result<(), Box> { let app = req.app().clone(); req.mut_extensions().insert(Transaction::new(app)); Ok(()) } - fn after(&self, req: &mut Request, res: Result>) - -> Result> { - let tx = req.mut_extensions().pop::() - .expect("Transaction not present in request"); + fn after(&self, req: &mut Request, res: Result>) -> Result> { + let tx = req.mut_extensions() + .pop::() + .expect("Transaction not present in request"); if let Some(transaction) = tx.tx.into_inner() { if res.is_ok() && tx.commit.get() == Some(true) { transaction.set_commit(); } - transaction.finish().map_err(|e| { - Box::new(e) as Box - })?; + transaction + .finish() + .map_err(|e| Box::new(e) as Box)?; } res } @@ -225,24 +223,26 @@ pub trait RequestTransaction { impl RequestTransaction for T { fn db_conn(&self) -> CargoResult { - self.app().diesel_database.get() - .map_err(Into::into) + self.app().diesel_database.get().map_err(Into::into) } fn tx(&self) -> CargoResult<&GenericConnection> { - self.extensions().find::() + self.extensions() + .find::() .expect("Transaction not present in request") .tx() } fn rollback(&self) { - self.extensions().find::() + self.extensions() + .find::() .expect("Transaction not present in request") .rollback() } fn commit(&self) { - self.extensions().find::() + self.extensions() + .find::() .expect("Transaction not present in request") .commit() } diff --git a/src/dependency.rs b/src/dependency.rs index 08e3f3cc06f..0ceefa31160 100644 --- a/src/dependency.rs +++ b/src/dependency.rs @@ -72,20 +72,37 @@ pub struct NewDependency<'a> { impl Dependency { // FIXME: Encapsulate this in a `NewDependency` struct #[cfg_attr(feature = "clippy", allow(too_many_arguments))] - pub fn insert(conn: &GenericConnection, version_id: i32, crate_id: i32, - req: &semver::VersionReq, kind: Kind, - optional: bool, default_features: bool, - features: &[String], target: &Option) - -> CargoResult { + pub fn insert( + conn: &GenericConnection, + version_id: i32, + crate_id: i32, + req: &semver::VersionReq, + kind: Kind, + optional: bool, + default_features: bool, + features: &[String], + target: &Option, + ) -> CargoResult { let req = req.to_string(); - let stmt = conn.prepare("INSERT INTO dependencies + let stmt = conn.prepare( + "INSERT INTO dependencies (version_id, crate_id, req, optional, default_features, features, target, kind) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) - RETURNING *")?; - let rows = stmt.query(&[&version_id, &crate_id, &req, - &optional, &default_features, - &features, target, &(kind as i32)])?; + RETURNING *" + )?; + let rows = stmt.query( + &[ + &version_id, + &crate_id, + &req, + &optional, + &default_features, + &features, + target, + &(kind as i32), + ] + )?; Ok(Model::from_row(&rows.iter().next().unwrap())) } @@ -108,65 +125,68 @@ impl Dependency { impl ReverseDependency { pub fn encodable(self) -> EncodableDependency { - self.dependency.encodable(&self.crate_name, Some(self.crate_downloads)) + self.dependency + .encodable(&self.crate_name, Some(self.crate_downloads)) } } -pub fn add_dependencies( - conn: &PgConnection, - deps: &[::upload::CrateDependency], - version_id: i32, -) -> CargoResult> { +pub fn add_dependencies(conn: &PgConnection, deps: &[::upload::CrateDependency], version_id: i32) -> CargoResult> { use diesel::insert; - let git_and_new_dependencies = deps.iter().map(|dep| { - let krate = Crate::by_name(&dep.name).first::(&*conn) - .map_err(|_| { - human(&format_args!("no known crate named `{}`", &*dep.name)) - })?; - if dep.version_req == semver::VersionReq::parse("*").unwrap() { - return Err(human("wildcard (`*`) dependency constraints are not allowed \ + let git_and_new_dependencies = deps.iter() + .map( + |dep| { + let krate = Crate::by_name(&dep.name) + .first::(&*conn) + .map_err(|_| human(&format_args!("no known crate named `{}`", &*dep.name)))?; + if dep.version_req == semver::VersionReq::parse("*").unwrap() { + return Err( + human( + "wildcard (`*`) dependency constraints are not allowed \ on crates.io. See http://doc.crates.io/faq.html#can-\ libraries-use--as-a-version-for-their-dependencies for more \ - information")); - } - let features: Vec<_> = dep.features.iter().map(|s| &**s).collect(); - - Ok(( - git::Dependency { - name: dep.name.to_string(), - req: dep.version_req.to_string(), - features: features.iter().map(|s| s.to_string()).collect(), - optional: dep.optional, - default_features: dep.default_features, - target: dep.target.clone(), - kind: dep.kind.or(Some(Kind::Normal)), - }, - NewDependency { - version_id: version_id, - crate_id: krate.id, - req: dep.version_req.to_string(), - kind: dep.kind.unwrap_or(Kind::Normal) as i32, - optional: dep.optional, - default_features: dep.default_features, - features: features, - target: dep.target.as_ref().map(|s| &**s), + information" + ) + ); + } + let features: Vec<_> = dep.features.iter().map(|s| &**s).collect(); + + Ok( + (git::Dependency { + name: dep.name.to_string(), + req: dep.version_req.to_string(), + features: features.iter().map(|s| s.to_string()).collect(), + optional: dep.optional, + default_features: dep.default_features, + target: dep.target.clone(), + kind: dep.kind.or(Some(Kind::Normal)), + }, + NewDependency { + version_id: version_id, + crate_id: krate.id, + req: dep.version_req.to_string(), + kind: dep.kind.unwrap_or(Kind::Normal) as i32, + optional: dep.optional, + default_features: dep.default_features, + features: features, + target: dep.target.as_ref().map(|s| &**s), + }) + ) } - )) - }).collect::, _>>()?; + ) + .collect::, _>>()?; - let (git_deps, new_dependencies): (Vec<_>, Vec<_>) = - git_and_new_dependencies.into_iter().unzip(); + let (git_deps, new_dependencies): (Vec<_>, Vec<_>) = git_and_new_dependencies.into_iter().unzip(); - insert(&new_dependencies).into(dependencies::table) + insert(&new_dependencies) + .into(dependencies::table) .execute(conn)?; Ok(git_deps) } impl Queryable for Dependency { - type Row = (i32, i32, i32, String, bool, bool, Vec, Option, - i32); + type Row = (i32, i32, i32, String, bool, bool, Vec, Option, i32); fn build(row: Self::Row) -> Self { Dependency { @@ -183,7 +203,7 @@ impl Queryable for Dependency { 1 => Kind::Build, 2 => Kind::Dev, n => panic!("unknown kind: {}", n), - } + }, } } } @@ -205,11 +225,13 @@ impl Model for Dependency { 1 => Kind::Build, 2 => Kind::Dev, n => panic!("unknown kind: {}", n), - } + }, } } - fn table_name(_: Option) -> &'static str { "dependencies" } + fn table_name(_: Option) -> &'static str { + "dependencies" + } } impl Model for ReverseDependency { @@ -221,5 +243,7 @@ impl Model for ReverseDependency { } } - fn table_name(_: Option) -> &'static str { panic!("no table") } + fn table_name(_: Option) -> &'static str { + panic!("no table") + } } diff --git a/src/dist.rs b/src/dist.rs index 3ba232629bf..1d3aac80f53 100644 --- a/src/dist.rs +++ b/src/dist.rs @@ -11,7 +11,7 @@ pub struct Middleware { dist: Static, } -impl Default for Middleware { +impl Default for Middleware { fn default() -> Middleware { Middleware { handler: None, @@ -27,7 +27,7 @@ impl AroundMiddleware for Middleware { } impl Handler for Middleware { - fn call(&self, req: &mut Request) -> Result> { + fn call(&self, req: &mut Request) -> Result> { // First, attempt to serve a static file. If we're missing a static // file, then keep going. match self.dist.call(req) { @@ -37,15 +37,19 @@ impl Handler for Middleware { // Second, if we're requesting html, then we've only got one page so // serve up that page. Otherwise proxy on to the rest of the app. - let wants_html = req.headers().find("Accept").map(|accept| { - accept.iter().any(|s| s.contains("html")) - }).unwrap_or(false); + let wants_html = req.headers() + .find("Accept") + .map(|accept| accept.iter().any(|s| s.contains("html"))) + .unwrap_or(false); if wants_html { - self.dist.call(&mut RequestProxy { - other: req, - path: Some("/index.html"), - method: None, - }) + self.dist + .call( + &mut RequestProxy { + other: req, + path: Some("/index.html"), + method: None, + } + ) } else { self.handler.as_ref().unwrap().call(req) } diff --git a/src/download.rs b/src/download.rs index 0df4d0c8cee..3e54c6ba76f 100644 --- a/src/download.rs +++ b/src/download.rs @@ -21,7 +21,10 @@ pub struct VersionDownload { #[derive(Insertable)] #[table_name="version_downloads"] -struct NewVersionDownload(#[column_name(version_id)] i32); +struct NewVersionDownload( + #[column_name(version_id)] + i32 +); #[derive(RustcEncodable, RustcDecodable)] pub struct EncodableVersionDownload { @@ -40,11 +43,13 @@ impl VersionDownload { // nothing else. We have lots of other counters, but they're // all updated later on via the update-downloads script. let new_download = NewVersionDownload(version); - let downloads_row = new_download - .on_conflict((version_id, date), do_update().set( - downloads.eq(downloads + 1) - )); - diesel::insert(&downloads_row).into(version_downloads).execute(conn)?; + let downloads_row = new_download.on_conflict( + (version_id, date), + do_update().set(downloads.eq(downloads + 1)), + ); + diesel::insert(&downloads_row) + .into(version_downloads) + .execute(conn)?; Ok(()) } @@ -70,5 +75,7 @@ impl Model for VersionDownload { } } - fn table_name(_: Option) -> &'static str { "version_downloads" } + fn table_name(_: Option) -> &'static str { + "version_downloads" + } } diff --git a/src/git.rs b/src/git.rs index ac97a3d1ab0..33ad587d075 100644 --- a/src/git.rs +++ b/src/git.rs @@ -34,14 +34,14 @@ pub struct Dependency { } fn index_file(base: &Path, name: &str) -> PathBuf { - let name = name.chars().flat_map(|c| c.to_lowercase()).collect::(); + let name = name.chars() + .flat_map(|c| c.to_lowercase()) + .collect::(); match name.len() { 1 => base.join("1").join(&name), 2 => base.join("2").join(&name), 3 => base.join("3").join(&name[..1]).join(&name), - _ => base.join(&name[0..2]) - .join(&name[2..4]) - .join(&name), + _ => base.join(&name[0..2]).join(&name[2..4]).join(&name), } } @@ -51,58 +51,67 @@ pub fn add_crate(app: &App, krate: &Crate) -> CargoResult<()> { let repo_path = repo.workdir().unwrap(); let dst = index_file(repo_path, &krate.name); - commit_and_push(repo, || { - // Add the crate to its relevant file - fs::create_dir_all(dst.parent().unwrap())?; - let mut prev = String::new(); - if fs::metadata(&dst).is_ok() { - File::open(&dst).and_then(|mut f| f.read_to_string(&mut prev))?; + commit_and_push( + repo, || { + // Add the crate to its relevant file + fs::create_dir_all(dst.parent().unwrap())?; + let mut prev = String::new(); + if fs::metadata(&dst).is_ok() { + File::open(&dst) + .and_then(|mut f| f.read_to_string(&mut prev))?; + } + let s = json::encode(krate).unwrap(); + let new = prev + &s; + let mut f = File::create(&dst)?; + f.write_all(new.as_bytes())?; + f.write_all(b"\n")?; + + Ok((format!("Updating crate `{}#{}`", krate.name, krate.vers), dst.clone())) } - let s = json::encode(krate).unwrap(); - let new = prev + &s; - let mut f = File::create(&dst)?; - f.write_all(new.as_bytes())?; - f.write_all(b"\n")?; - - Ok((format!("Updating crate `{}#{}`", krate.name, krate.vers), - dst.clone())) - }) + ) } -pub fn yank(app: &App, krate: &str, version: &semver::Version, - yanked: bool) -> CargoResult<()> { +pub fn yank(app: &App, krate: &str, version: &semver::Version, yanked: bool) -> CargoResult<()> { let repo = app.git_repo.lock().unwrap(); let repo_path = repo.workdir().unwrap(); let dst = index_file(repo_path, krate); - commit_and_push(&repo, || { - let mut prev = String::new(); - File::open(&dst).and_then(|mut f| f.read_to_string(&mut prev))?; - let new = prev.lines().map(|line| { - let mut git_crate = json::decode::(line).map_err(|_| { - internal(&format_args!("couldn't decode: `{}`", line)) - })?; - if git_crate.name != krate || - git_crate.vers != version.to_string() { - return Ok(line.to_string()) - } - git_crate.yanked = Some(yanked); - Ok(json::encode(&git_crate).unwrap()) - }).collect::>>(); - let new = new?.join("\n"); - let mut f = File::create(&dst)?; - f.write_all(new.as_bytes())?; - f.write_all(b"\n")?; - - Ok((format!("{} crate `{}#{}`", + commit_and_push( + &repo, || { + let mut prev = String::new(); + File::open(&dst) + .and_then(|mut f| f.read_to_string(&mut prev))?; + let new = prev.lines() + .map( + |line| { + let mut git_crate = json::decode::(line) + .map_err(|_| internal(&format_args!("couldn't decode: `{}`", line)))?; + if git_crate.name != krate || git_crate.vers != version.to_string() { + return Ok(line.to_string()); + } + git_crate.yanked = Some(yanked); + Ok(json::encode(&git_crate).unwrap()) + } + ) + .collect::>>(); + let new = new?.join("\n"); + let mut f = File::create(&dst)?; + f.write_all(new.as_bytes())?; + f.write_all(b"\n")?; + + Ok( + (format!("{} crate `{}#{}`", if yanked {"Yanking"} else {"Unyanking"}, krate, version), - dst.clone())) - }) + dst.clone()) + ) + } + ) } fn commit_and_push(repo: &git2::Repository, mut f: F) -> CargoResult<()> - where F: FnMut() -> CargoResult<(String, PathBuf)> +where + F: FnMut() -> CargoResult<(String, PathBuf)>, { let repo_path = repo.workdir().unwrap(); @@ -116,8 +125,9 @@ fn commit_and_push(repo: &git2::Repository, mut f: F) -> CargoResult<()> // git add $file let mut index = repo.index()?; let mut repo_path = repo_path.iter(); - let dst = dst.iter().skip_while(|s| Some(*s) == repo_path.next()) - .collect::(); + let dst = dst.iter() + .skip_while(|s| Some(*s) == repo_path.next()) + .collect::(); index.add_path(&dst)?; index.write()?; let tree_id = index.write_tree()?; @@ -135,11 +145,13 @@ fn commit_and_push(repo: &git2::Repository, mut f: F) -> CargoResult<()> let res = { let mut callbacks = git2::RemoteCallbacks::new(); callbacks.credentials(credentials); - callbacks.push_update_reference(|refname, status| { - assert_eq!(refname, "refs/heads/master"); - ref_status = status.map(|s| s.to_string()); - Ok(()) - }); + callbacks.push_update_reference( + |refname, status| { + assert_eq!(refname, "refs/heads/master"); + ref_status = status.map(|s| s.to_string()); + Ok(()) + } + ); let mut opts = git2::PushOptions::new(); opts.remote_callbacks(callbacks); origin.push(&["refs/heads/master"], Some(&mut opts)) @@ -152,9 +164,13 @@ fn commit_and_push(repo: &git2::Repository, mut f: F) -> CargoResult<()> let mut callbacks = git2::RemoteCallbacks::new(); callbacks.credentials(credentials); - origin.update_tips(Some(&mut callbacks), true, - git2::AutotagOption::Unspecified, - None)?; + origin + .update_tips( + Some(&mut callbacks), + true, + git2::AutotagOption::Unspecified, + None, + )?; // Ok, we need to update, so fetch and reset --hard origin.fetch(&["refs/heads/*:refs/heads/*"], None, None)?; @@ -166,13 +182,9 @@ fn commit_and_push(repo: &git2::Repository, mut f: F) -> CargoResult<()> Err(internal("Too many rebase failures")) } -pub fn credentials(_user: &str, _user_from_url: Option<&str>, - _cred: git2::CredentialType) - -> Result { +pub fn credentials(_user: &str, _user_from_url: Option<&str>, _cred: git2::CredentialType) -> Result { match (env::var("GIT_HTTP_USER"), env::var("GIT_HTTP_PWD")) { - (Ok(u), Ok(p)) => { - git2::Cred::userpass_plaintext(&u, &p) - } - _ => Err(git2::Error::from_str("no authentication set")) + (Ok(u), Ok(p)) => git2::Cred::userpass_plaintext(&u, &p), + _ => Err(git2::Error::from_str("no authentication set")), } } diff --git a/src/http.rs b/src/http.rs index a62cd3ad1b7..3e3e9c20d0a 100644 --- a/src/http.rs +++ b/src/http.rs @@ -10,15 +10,18 @@ use std::str; /// Does all the nonsense for sending a GET to Github. Doesn't handle parsing /// because custom error-code handling may be desirable. Use /// `parse_github_response` to handle the "common" processing of responses. -pub fn github(app: &App, url: &str, auth: &Token) - -> Result<(Easy, Vec), curl::Error> { +pub fn github(app: &App, url: &str, auth: &Token) -> Result<(Easy, Vec), curl::Error> { let url = format!("{}://api.github.com{}", app.config.api_protocol, url); info!("GITHUB HTTP: {}", url); let mut headers = List::new(); - headers.append("Accept: application/vnd.github.v3+json").unwrap(); + headers + .append("Accept: application/vnd.github.v3+json") + .unwrap(); headers.append("User-Agent: hello!").unwrap(); - headers.append(&format!("Authorization: token {}", auth.access_token)).unwrap(); + headers + .append(&format!("Authorization: token {}", auth.access_token)) + .unwrap(); let mut handle = app.handle(); handle.url(&url).unwrap(); @@ -28,43 +31,52 @@ pub fn github(app: &App, url: &str, auth: &Token) let mut data = Vec::new(); { let mut transfer = handle.transfer(); - transfer.write_function(|buf| { - data.extend_from_slice(buf); - Ok(buf.len()) - }).unwrap(); + transfer + .write_function( + |buf| { + data.extend_from_slice(buf); + Ok(buf.len()) + } + ) + .unwrap(); transfer.perform()?; } Ok((handle, data)) } /// Checks for normal responses -pub fn parse_github_response(mut resp: Easy, data: &[u8]) - -> CargoResult { +pub fn parse_github_response(mut resp: Easy, data: &[u8]) -> CargoResult { match resp.response_code().unwrap() { 200 => {} // Ok! 403 => { - return Err(human("It looks like you don't have permission \ + return Err( + human( + "It looks like you don't have permission \ to query a necessary property from Github \ to complete this request. \ You may need to re-authenticate on \ crates.io to grant permission to read \ github org memberships. Just go to \ - https://crates.io/login")); + https://crates.io/login" + ) + ); } n => { let resp = String::from_utf8_lossy(data); - return Err(internal(&format_args!("didn't get a 200 result from \ - github, got {} with: {}", n, resp))); + return Err( + internal( + &format_args!("didn't get a 200 result from \ + github, got {} with: {}", n, resp) + ) + ); } } - let json = str::from_utf8(data).ok().chain_error(|| { - internal("github didn't send a utf8-response") - })?; + let json = str::from_utf8(data) + .ok() + .chain_error(|| internal("github didn't send a utf8-response"))?; - json::decode(json).chain_error(|| { - internal("github didn't send a valid json response") - }) + json::decode(json).chain_error(|| internal("github didn't send a valid json response")) } /// Gets a token with the given string as the access token, but all diff --git a/src/keyword.rs b/src/keyword.rs index 6c53d5877ad..b3cbfed7142 100644 --- a/src/keyword.rs +++ b/src/keyword.rs @@ -40,8 +40,7 @@ pub struct EncodableKeyword { } impl Keyword { - pub fn find_by_keyword(conn: &PgConnection, name: &str) - -> QueryResult { + pub fn find_by_keyword(conn: &PgConnection, name: &str) -> QueryResult { keywords::table .filter(keywords::keyword.eq(::lower(name))) .first(&*conn) @@ -57,11 +56,10 @@ impl Keyword { keyword: &'a str, } - let lowercase_names: Vec<_> = names.iter() - .map(|s| s.to_lowercase()) - .collect(); + let lowercase_names: Vec<_> = names.iter().map(|s| s.to_lowercase()).collect(); - let new_keywords: Vec<_> = lowercase_names.iter() + let new_keywords: Vec<_> = lowercase_names + .iter() .map(|s| NewKeyword { keyword: s }) .collect(); @@ -77,14 +75,21 @@ impl Keyword { } pub fn valid_name(name: &str) -> bool { - if name.is_empty() { return false } + if name.is_empty() { + return false; + } name.chars().next().unwrap().is_alphanumeric() && - name.chars().all(|c| c.is_alphanumeric() || c == '_' || c == '-') && - name.chars().all(|c| c.is_ascii()) + name.chars() + .all(|c| c.is_alphanumeric() || c == '_' || c == '-') && name.chars().all(|c| c.is_ascii()) } pub fn encodable(self) -> EncodableKeyword { - let Keyword { crates_cnt, keyword, created_at, .. } = self; + let Keyword { + crates_cnt, + keyword, + created_at, + .. + } = self; EncodableKeyword { id: keyword.clone(), created_at: ::encode_time(created_at), @@ -93,20 +98,29 @@ impl Keyword { } } - pub fn update_crate(conn: &PgConnection, - krate: &Crate, - keywords: &[&str]) -> QueryResult<()> { - conn.transaction(|| { - let keywords = Keyword::find_or_create_all(conn, keywords)?; - diesel::delete(CrateKeyword::belonging_to(krate)) - .execute(conn)?; - let crate_keywords = keywords.into_iter().map(|kw| { - CrateKeyword { crate_id: krate.id, keyword_id: kw.id } - }).collect::>(); - diesel::insert(&crate_keywords).into(crates_keywords::table) - .execute(conn)?; - Ok(()) - }) + pub fn update_crate(conn: &PgConnection, krate: &Crate, keywords: &[&str]) -> QueryResult<()> { + conn.transaction( + || { + let keywords = Keyword::find_or_create_all(conn, keywords)?; + diesel::delete(CrateKeyword::belonging_to(krate)) + .execute(conn)?; + let crate_keywords = keywords + .into_iter() + .map( + |kw| { + CrateKeyword { + crate_id: krate.id, + keyword_id: kw.id, + } + } + ) + .collect::>(); + diesel::insert(&crate_keywords) + .into(crates_keywords::table) + .execute(conn)?; + Ok(()) + } + ) } } @@ -119,7 +133,9 @@ impl Model for Keyword { keyword: row.get("keyword"), } } - fn table_name(_: Option) -> &'static str { "keywords" } + fn table_name(_: Option) -> &'static str { + "keywords" + } } /// Handles the `GET /keywords` route. @@ -148,17 +164,27 @@ pub fn index(req: &mut Request) -> CargoResult { let data = query.load::<(Keyword, i64)>(&*conn)?; let total = data.get(0).map(|&(_, t)| t).unwrap_or(0); let kws = data.into_iter() - .map(|(k, _)| k.encodable()).collect::>(); + .map(|(k, _)| k.encodable()) + .collect::>(); #[derive(RustcEncodable)] - struct R { keywords: Vec, meta: Meta } + struct R { + keywords: Vec, + meta: Meta, + } #[derive(RustcEncodable)] - struct Meta { total: i64 } + struct Meta { + total: i64, + } - Ok(req.json(&R { - keywords: kws, - meta: Meta { total: total }, - })) + Ok( + req.json( + &R { + keywords: kws, + meta: Meta { total: total }, + } + ) + ) } /// Handles the `GET /keywords/:keyword_id` route. @@ -169,6 +195,8 @@ pub fn show(req: &mut Request) -> CargoResult { let kw = Keyword::find_by_keyword(&conn, name)?; #[derive(RustcEncodable)] - struct R { keyword: EncodableKeyword } + struct R { + keyword: EncodableKeyword, + } Ok(req.json(&R { keyword: kw.encodable() })) } diff --git a/src/krate.rs b/src/krate.rs index 9323825567c..a3953298668 100644 --- a/src/krate.rs +++ b/src/krate.rs @@ -56,16 +56,31 @@ pub struct Crate { /// We literally never want to select `textsearchable_index_col` /// so we provide this type and constant to pass to `.select` -type AllColumns = (crates::id, crates::name, crates::updated_at, - crates::created_at, crates::downloads, crates::description, - crates::homepage, crates::documentation, crates::readme, crates::license, - crates::repository, crates::max_upload_size); - -pub const ALL_COLUMNS: AllColumns = (crates::id, crates::name, - crates::updated_at, crates::created_at, crates::downloads, - crates::description, crates::homepage, crates::documentation, - crates::readme, crates::license, crates::repository, - crates::max_upload_size); +type AllColumns = (crates::id, + crates::name, + crates::updated_at, + crates::created_at, + crates::downloads, + crates::description, + crates::homepage, + crates::documentation, + crates::readme, + crates::license, + crates::repository, + crates::max_upload_size); + +pub const ALL_COLUMNS: AllColumns = (crates::id, + crates::name, + crates::updated_at, + crates::created_at, + crates::downloads, + crates::description, + crates::homepage, + crates::documentation, + crates::readme, + crates::license, + crates::repository, + crates::max_upload_size); pub const MAX_NAME_LENGTH: usize = 64; @@ -115,51 +130,56 @@ pub struct NewCrate<'a> { } impl<'a> NewCrate<'a> { - pub fn create_or_update( - mut self, - conn: &PgConnection, - license_file: Option<&str>, - uploader: i32, - ) -> CargoResult { + pub fn create_or_update(mut self, conn: &PgConnection, license_file: Option<&str>, uploader: i32) -> CargoResult { use diesel::update; self.validate(license_file)?; self.ensure_name_not_reserved(conn)?; - conn.transaction(|| { - // To avoid race conditions, we try to insert - // first so we know whether to add an owner - if let Some(krate) = self.save_new_crate(conn, uploader)? { - return Ok(krate) + conn.transaction( + || { + // To avoid race conditions, we try to insert + // first so we know whether to add an owner + if let Some(krate) = self.save_new_crate(conn, uploader)? { + return Ok(krate); + } + + let target = crates::table.filter(canon_crate_name(crates::name).eq(canon_crate_name(self.name))); + update(target) + .set(&self) + .returning(ALL_COLUMNS) + .get_result(conn) + .map_err(Into::into) } - - let target = crates::table.filter( - canon_crate_name(crates::name) - .eq(canon_crate_name(self.name))); - update(target).set(&self) - .returning(ALL_COLUMNS) - .get_result(conn) - .map_err(Into::into) - }) + ) } fn validate(&mut self, license_file: Option<&str>) -> CargoResult<()> { fn validate_url(url: Option<&str>, field: &str) -> CargoResult<()> { let url = match url { Some(s) => s, - None => return Ok(()) + None => return Ok(()), }; - let url = Url::parse(url).map_err(|_| { - human(&format_args!("`{}` is not a valid url: `{}`", field, url)) - })?; + let url = Url::parse(url) + .map_err(|_| human(&format_args!("`{}` is not a valid url: `{}`", field, url)))?; match &url.scheme()[..] { "http" | "https" => {} - s => return Err(human(&format_args!("`{}` has an invalid url \ - scheme: `{}`", field, s))) + s => { + return Err( + human( + &format_args!("`{}` has an invalid url \ + scheme: `{}`", field, s) + ) + ) + } } if url.cannot_be_a_base() { - return Err(human(&format_args!("`{}` must have relative scheme \ - data: {}", field, url))) + return Err( + human( + &format_args!("`{}` must have relative scheme \ + data: {}", field, url) + ) + ); } Ok(()) } @@ -174,10 +194,16 @@ impl<'a> NewCrate<'a> { fn validate_license(&mut self, license_file: Option<&str>) -> CargoResult<()> { if let Some(license) = self.license { for part in license.split('/') { - license_exprs::validate_license_expr(part) - .map_err(|e| human(&format_args!("{}; see http://opensource.org/licenses \ + license_exprs::validate_license_expr(part) + .map_err( + |e| { + human( + &format_args!("{}; see http://opensource.org/licenses \ for options, and http://spdx.org/licenses/ \ - for their identifiers", e)))?; + for their identifiers", e) + ) + } + )?; } } else if license_file.is_some() { // If no license is given, but a license file is given, flag this @@ -193,9 +219,8 @@ impl<'a> NewCrate<'a> { use diesel::select; use diesel::expression::dsl::exists; - let reserved_name = select(exists(reserved_crate_names - .filter(canon_crate_name(name).eq(canon_crate_name(self.name))) - )).get_result::(conn)?; + let reserved_name = select(exists(reserved_crate_names.filter(canon_crate_name(name).eq(canon_crate_name(self.name))))) + .get_result::(conn)?; if reserved_name { Err(human("cannot upload a crate with a reserved name")) } else { @@ -207,46 +232,47 @@ impl<'a> NewCrate<'a> { use schema::crates::dsl::*; use diesel::insert; - conn.transaction(|| { - let maybe_inserted = insert(&self.on_conflict_do_nothing()).into(crates) - .returning(ALL_COLUMNS) - .get_result::(conn) - .optional()?; - - if let Some(ref krate) = maybe_inserted { - let owner = CrateOwner { - crate_id: krate.id, - owner_id: user_id, - created_by: user_id, - owner_kind: OwnerKind::User as i32, - }; - insert(&owner).into(crate_owners::table) - .execute(conn)?; + conn.transaction( + || { + let maybe_inserted = insert(&self.on_conflict_do_nothing()) + .into(crates) + .returning(ALL_COLUMNS) + .get_result::(conn) + .optional()?; + + if let Some(ref krate) = maybe_inserted { + let owner = CrateOwner { + crate_id: krate.id, + owner_id: user_id, + created_by: user_id, + owner_kind: OwnerKind::User as i32, + }; + insert(&owner).into(crate_owners::table).execute(conn)?; + } + + Ok(maybe_inserted) } - - Ok(maybe_inserted) - }) + ) } } impl Crate { pub fn by_name(name: &str) -> CrateQuery { Crate::all() - .filter( - canon_crate_name(crates::name).eq( - canon_crate_name(name)) - ).into_boxed() + .filter(canon_crate_name(crates::name).eq(canon_crate_name(name))) + .into_boxed() } pub fn all() -> Select { crates::table.select(ALL_COLUMNS) } - pub fn find_by_name(conn: &GenericConnection, - name: &str) -> CargoResult { - let stmt = conn.prepare("SELECT * FROM crates \ + pub fn find_by_name(conn: &GenericConnection, name: &str) -> CargoResult { + let stmt = conn.prepare( + "SELECT * FROM crates \ WHERE canon_crate_name(name) = - canon_crate_name($1) LIMIT 1")?; + canon_crate_name($1) LIMIT 1" + )?; let rows = stmt.query(&[&name])?; let row = rows.iter().next(); let row = row.chain_error(|| NotFound)?; @@ -255,18 +281,19 @@ impl Crate { // This is cleaned up by the diesel port #[cfg_attr(feature = "lint", allow(too_many_arguments))] - pub fn find_or_insert(conn: &GenericConnection, - name: &str, - user_id: i32, - description: &Option, - homepage: &Option, - documentation: &Option, - readme: &Option, - repository: &Option, - license: &Option, - license_file: &Option, - max_upload_size: Option) - -> CargoResult { + pub fn find_or_insert( + conn: &GenericConnection, + name: &str, + user_id: i32, + description: &Option, + homepage: &Option, + documentation: &Option, + readme: &Option, + repository: &Option, + license: &Option, + license_file: &Option, + max_upload_size: Option, + ) -> CargoResult { let description = description.as_ref().map(|s| &s[..]); let homepage = homepage.as_ref().map(|s| &s[..]); let documentation = documentation.as_ref().map(|s| &s[..]); @@ -294,7 +321,8 @@ impl Crate { } // TODO: like with users, this is sadly racy - let stmt = conn.prepare("UPDATE crates + let stmt = conn.prepare( + "UPDATE crates SET documentation = $1, homepage = $2, description = $3, @@ -303,86 +331,128 @@ impl Crate { repository = $6 WHERE canon_crate_name(name) = canon_crate_name($7) - RETURNING *")?; - let rows = stmt.query(&[&documentation, &homepage, - &description, &readme, - &license, &repository, - &name])?; + RETURNING *" + )?; + let rows = stmt.query( + &[ + &documentation, + &homepage, + &description, + &readme, + &license, + &repository, + &name, + ] + )?; if let Some(row) = rows.iter().next() { return Ok(Model::from_row(&row)); } - let stmt = conn.prepare("SELECT 1 FROM reserved_crate_names + let stmt = conn.prepare( + "SELECT 1 FROM reserved_crate_names WHERE canon_crate_name(name) = - canon_crate_name($1)")?; + canon_crate_name($1)" + )?; let rows = stmt.query(&[&name])?; if !rows.is_empty() { - return Err(human("cannot upload a crate with a reserved name")) + return Err(human("cannot upload a crate with a reserved name")); } - let stmt = conn.prepare("INSERT INTO crates + let stmt = conn.prepare( + "INSERT INTO crates (name, description, homepage, documentation, readme, repository, license, max_upload_size) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) - RETURNING *")?; - let rows = stmt.query(&[&name, &description, &homepage, - &documentation, &readme, - &repository, &license, &max_upload_size])?; - let ret: Crate = Model::from_row(&rows.iter().next().chain_error(|| { - internal("no crate returned") - })?); - - conn.execute("INSERT INTO crate_owners + RETURNING *" + )?; + let rows = stmt.query( + &[ + &name, + &description, + &homepage, + &documentation, + &readme, + &repository, + &license, + &max_upload_size, + ] + )?; + let ret: Crate = Model::from_row( + &rows.iter() + .next() + .chain_error(|| internal("no crate returned"))? + ); + + conn.execute( + "INSERT INTO crate_owners (crate_id, owner_id, created_by, owner_kind) VALUES ($1, $2, $2, $3)", - &[&ret.id, &user_id, &(OwnerKind::User as i32)])?; + &[&ret.id, &user_id, &(OwnerKind::User as i32)], + )?; return Ok(ret); fn validate_url(url: Option<&str>, field: &str) -> CargoResult<()> { let url = match url { Some(s) => s, - None => return Ok(()) + None => return Ok(()), }; - let url = Url::parse(url).map_err(|_| { - human(&format_args!("`{}` is not a valid url: `{}`", field, url)) - })?; + let url = Url::parse(url) + .map_err(|_| human(&format_args!("`{}` is not a valid url: `{}`", field, url)))?; match &url.scheme()[..] { "http" | "https" => {} - s => return Err(human(&format_args!("`{}` has an invalid url \ - scheme: `{}`", field, s))) + s => { + return Err( + human( + &format_args!("`{}` has an invalid url \ + scheme: `{}`", field, s) + ) + ) + } } if url.cannot_be_a_base() { - return Err(human(&format_args!("`{}` must have relative scheme \ - data: {}", field, url))) + return Err( + human( + &format_args!("`{}` must have relative scheme \ + data: {}", field, url) + ) + ); } Ok(()) } fn validate_license(license: Option<&str>) -> CargoResult<()> { - license.iter().flat_map(|s| s.split('/')) - .map(license_exprs::validate_license_expr) - .collect::, _>>() - .map(|_| ()) - .map_err(|e| human(&format_args!("{}; see http://opensource.org/licenses \ + license + .iter() + .flat_map(|s| s.split('/')) + .map(license_exprs::validate_license_expr) + .collect::, _>>() + .map(|_| ()) + .map_err( + |e| { + human( + &format_args!("{}; see http://opensource.org/licenses \ for options, and http://spdx.org/licenses/ \ - for their identifiers", e))) + for their identifiers", e) + ) + } + ) } } pub fn valid_name(name: &str) -> bool { - let under_max_length = name.chars() - .take(MAX_NAME_LENGTH + 1) - .count() <= MAX_NAME_LENGTH; + let under_max_length = name.chars().take(MAX_NAME_LENGTH + 1).count() <= MAX_NAME_LENGTH; Crate::valid_ident(name) && under_max_length } fn valid_ident(name: &str) -> bool { - if name.is_empty() { return false } + if name.is_empty() { + return false; + } name.chars().next().unwrap().is_alphabetic() && - name.chars().all(|c| c.is_alphanumeric() || c == '_' || c == '-') && - name.chars().all(|c| c.is_ascii()) + name.chars() + .all(|c| c.is_alphanumeric() || c == '_' || c == '-') && name.chars().all(|c| c.is_ascii()) } pub fn valid_feature_name(name: &str) -> bool { @@ -399,23 +469,30 @@ impl Crate { parts.next().is_none() } - pub fn minimal_encodable(self, - max_version: semver::Version, - badges: Option>, exact_match: bool) -> EncodableCrate { + pub fn minimal_encodable(self, max_version: semver::Version, badges: Option>, exact_match: bool) -> EncodableCrate { self.encodable(max_version, None, None, None, badges, exact_match) } - pub fn encodable(self, - max_version: semver::Version, - versions: Option>, - keywords: Option<&[Keyword]>, - categories: Option<&[Category]>, - badges: Option>, - exact_match: bool) - -> EncodableCrate { + pub fn encodable( + self, + max_version: semver::Version, + versions: Option>, + keywords: Option<&[Keyword]>, + categories: Option<&[Category]>, + badges: Option>, + exact_match: bool, + ) -> EncodableCrate { let Crate { - name, created_at, updated_at, downloads, description, - homepage, documentation, license, repository, .. + name, + created_at, + updated_at, + downloads, + description, + homepage, + documentation, + license, + repository, + .. } = self; let versions_link = match versions { Some(..) => None, @@ -423,9 +500,7 @@ impl Crate { }; let keyword_ids = keywords.map(|kws| kws.iter().map(|kw| kw.keyword.clone()).collect()); let category_ids = categories.map(|cats| cats.iter().map(|cat| cat.slug.clone()).collect()); - let badges = badges.map(|bs| { - bs.into_iter().map(|b| b.encodable()).collect() - }); + let badges = badges.map(|bs| bs.into_iter().map(|b| b.encodable()).collect()); EncodableCrate { id: name.clone(), name: name.clone(), @@ -447,7 +522,7 @@ impl Crate { version_downloads: format!("/api/v1/crates/{}/downloads", name), versions: versions_link, owners: Some(format!("/api/v1/crates/{}/owners", name)), - reverse_dependencies: format!("/api/v1/crates/{}/reverse_dependencies", name) + reverse_dependencies: format!("/api/v1/crates/{}/reverse_dependencies", name), }, } } @@ -455,7 +530,8 @@ impl Crate { pub fn max_version(&self, conn: &PgConnection) -> CargoResult { use schema::versions::dsl::*; - let vs = Version::belonging_to(self).select(num) + let vs = Version::belonging_to(self) + .select(num) .filter(yanked.eq(false)) .load::(conn)? .into_iter() @@ -464,34 +540,44 @@ impl Crate { } pub fn max_version_old(&self, conn: &GenericConnection) -> CargoResult { - let stmt = conn.prepare("SELECT num FROM versions WHERE crate_id = $1 - AND yanked = 'f'")?; + let stmt = conn.prepare( + "SELECT num FROM versions WHERE crate_id = $1 + AND yanked = 'f'" + )?; let rows = stmt.query(&[&self.id])?; - Ok(Version::max(rows.iter().map(|r| r.get::<_, String>("num")) - .map(|s| semver::Version::parse(&s).unwrap()))) + Ok( + Version::max( + rows.iter() + .map(|r| r.get::<_, String>("num")) + .map(|s| semver::Version::parse(&s).unwrap()) + ) + ) } pub fn versions(&self, conn: &GenericConnection) -> CargoResult> { - let stmt = conn.prepare("SELECT * FROM versions \ - WHERE crate_id = $1")?; + let stmt = conn.prepare( + "SELECT * FROM versions \ + WHERE crate_id = $1" + )?; let rows = stmt.query(&[&self.id])?; - let mut ret = rows.iter().map(|r| { - Model::from_row(&r) - }).collect::>(); + let mut ret = rows.iter() + .map(|r| Model::from_row(&r)) + .collect::>(); ret.sort_by(|a, b| b.num.cmp(&a.num)); Ok(ret) } pub fn owners(&self, conn: &PgConnection) -> CargoResult> { - let base_query = CrateOwner::belonging_to(self) - .filter(crate_owners::deleted.eq(false)); - let users = base_query.inner_join(users::table) + let base_query = CrateOwner::belonging_to(self).filter(crate_owners::deleted.eq(false)); + let users = base_query + .inner_join(users::table) .select(users::all_columns) .filter(crate_owners::owner_kind.eq(OwnerKind::User as i32)) .load(conn)? .into_iter() .map(Owner::User); - let teams = base_query.inner_join(teams::table) + let teams = base_query + .inner_join(teams::table) .select(teams::all_columns) .filter(crate_owners::owner_kind.eq(OwnerKind::Team as i32)) .load(conn)? @@ -502,20 +588,24 @@ impl Crate { } pub fn owners_old(&self, conn: &GenericConnection) -> CargoResult> { - let stmt = conn.prepare("SELECT * FROM users + let stmt = conn.prepare( + "SELECT * FROM users INNER JOIN crate_owners ON crate_owners.owner_id = users.id WHERE crate_owners.crate_id = $1 AND crate_owners.deleted = FALSE - AND crate_owners.owner_kind = $2")?; + AND crate_owners.owner_kind = $2" + )?; let user_rows = stmt.query(&[&self.id, &(OwnerKind::User as i32)])?; - let stmt = conn.prepare("SELECT * FROM teams + let stmt = conn.prepare( + "SELECT * FROM teams INNER JOIN crate_owners ON crate_owners.owner_id = teams.id WHERE crate_owners.crate_id = $1 AND crate_owners.deleted = FALSE - AND crate_owners.owner_kind = $2")?; + AND crate_owners.owner_kind = $2" + )?; let team_rows = stmt.query(&[&self.id, &(OwnerKind::Team as i32)])?; let mut owners = vec![]; @@ -524,26 +614,28 @@ impl Crate { Ok(owners) } - pub fn owner_add( - &self, - app: &App, - conn: &PgConnection, - req_user: &User, - login: &str, - ) -> CargoResult<()> { + pub fn owner_add(&self, app: &App, conn: &PgConnection, req_user: &User, login: &str) -> CargoResult<()> { let owner = match Owner::find_by_login(conn, login) { - Ok(owner @ Owner::User(_)) => { owner } - Ok(Owner::Team(team)) => if team.contains_user(app, req_user)? { - Owner::Team(team) - } else { - return Err(human(&format_args!("only members of {} can add it as \ - an owner", login))); - }, - Err(err) => if login.contains(':') { - Owner::Team(Team::create(app, conn, login, req_user)?) - } else { - return Err(err); - }, + Ok(owner @ Owner::User(_)) => owner, + Ok(Owner::Team(team)) => { + if team.contains_user(app, req_user)? { + Owner::Team(team) + } else { + return Err( + human( + &format_args!("only members of {} can add it as \ + an owner", login) + ) + ); + } + } + Err(err) => { + if login.contains(':') { + Owner::Team(Team::create(app, conn, login, req_user)?) + } else { + return Err(err); + } + } }; let crate_owner = CrateOwner { @@ -552,73 +644,72 @@ impl Crate { created_by: req_user.id, owner_kind: owner.kind() as i32, }; - diesel::insert(&crate_owner.on_conflict( + diesel::insert( + &crate_owner.on_conflict( crate_owners::table.primary_key(), do_update().set(crate_owners::deleted.eq(false)), - )).into(crate_owners::table) - .execute(conn)?; + ) + ) + .into(crate_owners::table) + .execute(conn)?; Ok(()) } - pub fn owner_remove(&self, - conn: &PgConnection, - _req_user: &User, - login: &str) -> CargoResult<()> { - let owner = Owner::find_by_login(conn, login).map_err(|_| { - human(&format_args!("could not find owner with login `{}`", login)) - })?; - let target = crate_owners::table.find(( - self.id(), - owner.id(), - owner.kind() as i32, - )); - diesel::update(target).set(crate_owners::deleted.eq(true)) + pub fn owner_remove(&self, conn: &PgConnection, _req_user: &User, login: &str) -> CargoResult<()> { + let owner = Owner::find_by_login(conn, login) + .map_err(|_| human(&format_args!("could not find owner with login `{}`", login)))?; + let target = crate_owners::table.find((self.id(), owner.id(), owner.kind() as i32)); + diesel::update(target) + .set(crate_owners::deleted.eq(true)) .execute(conn)?; Ok(()) } - pub fn add_version(&mut self, - conn: &GenericConnection, - ver: &semver::Version, - features: &HashMap>, - authors: &[String]) - -> CargoResult { + pub fn add_version( + &mut self, + conn: &GenericConnection, + ver: &semver::Version, + features: &HashMap>, + authors: &[String], + ) -> CargoResult { if Version::find_by_num(conn, self.id, ver)?.is_some() { - return Err(human(&format_args!("crate version `{}` is already uploaded", ver))) + return Err(human(&format_args!("crate version `{}` is already uploaded", ver))); } Version::insert(conn, self.id, ver, features, authors) } pub fn keywords(&self, conn: &GenericConnection) -> CargoResult> { - let stmt = conn.prepare("SELECT keywords.* FROM keywords + let stmt = conn.prepare( + "SELECT keywords.* FROM keywords LEFT JOIN crates_keywords ON keywords.id = crates_keywords.keyword_id - WHERE crates_keywords.crate_id = $1")?; + WHERE crates_keywords.crate_id = $1" + )?; let rows = stmt.query(&[&self.id])?; Ok(rows.iter().map(|r| Model::from_row(&r)).collect()) } pub fn categories(&self, conn: &GenericConnection) -> CargoResult> { - let stmt = conn.prepare("SELECT categories.* FROM categories \ + let stmt = conn.prepare( + "SELECT categories.* FROM categories \ LEFT JOIN crates_categories \ ON categories.id = \ crates_categories.category_id \ - WHERE crates_categories.crate_id = $1")?; + WHERE crates_categories.crate_id = $1" + )?; let rows = stmt.query(&[&self.id])?; Ok(rows.iter().map(|r| Model::from_row(&r)).collect()) } pub fn badges(&self, conn: &PgConnection) -> QueryResult> { - badges::table.filter(badges::crate_id.eq(self.id)).load(conn) + badges::table + .filter(badges::crate_id.eq(self.id)) + .load(conn) } /// Returns (dependency, dependent crate name, dependent crate downloads) - pub fn reverse_dependencies(&self, - conn: &GenericConnection, - offset: i64, - limit: i64) - -> CargoResult<(Vec, i64)> { + pub fn reverse_dependencies(&self, conn: &GenericConnection, offset: i64, limit: i64) -> CargoResult<(Vec, i64)> { let stmt = conn.prepare(include_str!("krate_reverse_dependencies.sql"))?; let rows = stmt.query(&[&self.id, &offset, &limit])?; @@ -627,10 +718,7 @@ impl Crate { } else { rows.get(0).get("total") }; - let vec: Vec<_> = rows - .iter() - .map(|r| Model::from_row(&r)) - .collect(); + let vec: Vec<_> = rows.iter().map(|r| Model::from_row(&r)).collect(); Ok((vec, cnt)) } @@ -653,7 +741,9 @@ impl Model for Crate { max_upload_size: row.get("max_upload_size"), } } - fn table_name(_: Option) -> &'static str { "crates" } + fn table_name(_: Option) -> &'static str { + "crates" + } } /// Handles the `GET /crates` route. @@ -683,7 +773,7 @@ pub fn index(req: &mut Request) -> CargoResult { let q = plainto_tsquery(q_string); query = query.filter(q.matches(crates::textsearchable_index_col)); - query = query.select((ALL_COLUMNS, sql::("COUNT(*) OVER()"), crates::name.eq(q_string))); + query = query.select((ALL_COLUMNS, sql::("COUNT(*) OVER()"), crates::name.eq(q_string))); let perfect_match = crates::name.eq(q_string).desc(); if sort == "downloads" { query = query.order((perfect_match, crates::downloads.desc())); @@ -694,41 +784,57 @@ pub fn index(req: &mut Request) -> CargoResult { } if let Some(cat) = params.get("category") { - query = query.filter(crates::id.eq_any( - crates_categories::table.select(crates_categories::crate_id) - .inner_join(categories::table) - .filter(categories::slug.eq(cat).or( - categories::slug.like(format!("{}::%", cat)))) - )); + query = query.filter( + crates::id.eq_any( + crates_categories::table + .select(crates_categories::crate_id) + .inner_join(categories::table) + .filter( + categories::slug + .eq(cat) + .or(categories::slug.like(format!("{}::%", cat))) + ) + ) + ); } if let Some(kw) = params.get("keyword") { - query = query.filter(crates::id.eq_any( - crates_keywords::table.select(crates_keywords::crate_id) - .inner_join(keywords::table) - .filter(::lower(keywords::keyword).eq(::lower(kw))) - )); + query = query.filter( + crates::id.eq_any( + crates_keywords::table + .select(crates_keywords::crate_id) + .inner_join(keywords::table) + .filter(::lower(keywords::keyword).eq(::lower(kw))) + ) + ); } else if let Some(letter) = params.get("letter") { let pattern = format!("{}%", letter.chars().next().unwrap() .to_lowercase().collect::()); query = query.filter(canon_crate_name(crates::name).like(pattern)); - } - else if let Some(user_id) = params.get("user_id").and_then(|s| s.parse::().ok()) { - query = query.filter(crates::id.eq_any( - crate_owners::table.select(crate_owners::crate_id) - .filter(crate_owners::owner_id.eq(user_id)) - .filter(crate_owners::owner_kind.eq(OwnerKind::User as i32)) - )); + } else if let Some(user_id) = params.get("user_id").and_then(|s| s.parse::().ok()) { + query = query.filter( + crates::id.eq_any( + crate_owners::table + .select(crate_owners::crate_id) + .filter(crate_owners::owner_id.eq(user_id)) + .filter(crate_owners::owner_kind.eq(OwnerKind::User as i32)) + ) + ); } else if params.get("following").is_some() { - query = query.filter(crates::id.eq_any( - follows::table.select(follows::crate_id) - .filter(follows::user_id.eq(req.user()?.id)) - )); + query = query.filter( + crates::id.eq_any( + follows::table + .select(follows::crate_id) + .filter(follows::user_id.eq(req.user()?.id)) + ) + ); } let data = query.load::<(Crate, i64, bool)>(&*conn)?; let total = data.get(0).map(|&(_, t, _)| t).unwrap_or(0); - let crates = data.iter().map(|&(ref c, _, _)| c.clone()).collect::>(); + let crates = data.iter() + .map(|&(ref c, _, _)| c.clone()) + .collect::>(); let perfect_matches = data.into_iter().map(|(_, _, b)| b).collect::>(); let versions = Version::belonging_to(&crates) @@ -737,23 +843,39 @@ pub fn index(req: &mut Request) -> CargoResult { .into_iter() .map(|versions| Version::max(versions.into_iter().map(|v| v.num))); - let crates = versions.zip(crates).zip(perfect_matches).map(|((max_version, krate), perfect_match)| { - // FIXME: If we add crate_id to the Badge enum we can eliminate - // this N+1 - let badges = badges::table.filter(badges::crate_id.eq(krate.id)) - .load::(&*conn)?; - Ok(krate.minimal_encodable(max_version, Some(badges), perfect_match)) - }).collect::>()?; + let crates = versions + .zip(crates) + .zip(perfect_matches) + .map( + |((max_version, krate), perfect_match)| { + // FIXME: If we add crate_id to the Badge enum we can eliminate + // this N+1 + let badges = badges::table + .filter(badges::crate_id.eq(krate.id)) + .load::(&*conn)?; + Ok(krate.minimal_encodable(max_version, Some(badges), perfect_match)) + } + ) + .collect::>()?; #[derive(RustcEncodable)] - struct R { crates: Vec, meta: Meta } + struct R { + crates: Vec, + meta: Meta, + } #[derive(RustcEncodable)] - struct Meta { total: i64 } + struct Meta { + total: i64, + } - Ok(req.json(&R { - crates: crates, - meta: Meta { total: total }, - })) + Ok( + req.json( + &R { + crates: crates, + meta: Meta { total: total }, + } + ) + ) } /// Handles the `GET /summary` route. @@ -762,7 +884,8 @@ pub fn summary(req: &mut Request) -> CargoResult { let conn = req.db_conn()?; let num_crates = crates.count().get_result(&*conn)?; - let num_downloads = metadata::table.select(metadata::total_downloads) + let num_downloads = metadata::table + .select(metadata::total_downloads) .get_result(&*conn)?; let encode_crates = |krates: Vec| -> CargoResult> { @@ -773,26 +896,29 @@ pub fn summary(req: &mut Request) -> CargoResult { .into_iter() .map(|versions| Version::max(versions.into_iter().map(|v| v.num))) .zip(krates) - .map(|(max_version, krate)| { - Ok(krate.minimal_encodable(max_version, None, false)) - }).collect() + .map(|(max_version, krate)| Ok(krate.minimal_encodable(max_version, None, false))) + .collect() }; - let new_crates = crates.order(created_at.desc()) + let new_crates = crates + .order(created_at.desc()) .select(ALL_COLUMNS) .limit(10) .load(&*conn)?; - let just_updated = crates.filter(updated_at.ne(created_at)) + let just_updated = crates + .filter(updated_at.ne(created_at)) .order(updated_at.desc()) .select(ALL_COLUMNS) .limit(10) .load(&*conn)?; - let most_downloaded = crates.order(downloads.desc()) + let most_downloaded = crates + .order(downloads.desc()) .select(ALL_COLUMNS) .limit(10) .load(&*conn)?; - let popular_keywords = keywords::table.order(keywords::crates_cnt.desc()) + let popular_keywords = keywords::table + .order(keywords::crates_cnt.desc()) .limit(10) .load(&*conn)? .into_iter() @@ -814,15 +940,19 @@ pub fn summary(req: &mut Request) -> CargoResult { popular_keywords: Vec, popular_categories: Vec, } - Ok(req.json(&R { - num_downloads: num_downloads, - num_crates: num_crates, - new_crates: encode_crates(new_crates)?, - most_downloaded: encode_crates(most_downloaded)?, - just_updated: encode_crates(just_updated)?, - popular_keywords: popular_keywords, - popular_categories: popular_categories, - })) + Ok( + req.json( + &R { + num_downloads: num_downloads, + num_crates: num_crates, + new_crates: encode_crates(new_crates)?, + most_downloaded: encode_crates(most_downloaded)?, + just_updated: encode_crates(just_updated)?, + popular_keywords: popular_keywords, + popular_categories: popular_categories, + } + ) + ) } /// Handles the `GET /crates/:crate_id` route. @@ -844,7 +974,8 @@ pub fn show(req: &mut Request) -> CargoResult { .select(categories::all_columns) .load(&*conn)?; - let badges = badges::table.filter(badges::crate_id.eq(krate.id)) + let badges = badges::table + .filter(badges::crate_id.eq(krate.id)) .load(&*conn)?; let max_version = krate.max_version(&conn)?; @@ -855,16 +986,28 @@ pub fn show(req: &mut Request) -> CargoResult { keywords: Vec, categories: Vec, } - Ok(req.json(&R { - krate: krate.clone().encodable( - max_version, Some(ids), Some(&kws), Some(&cats), Some(badges), false - ), - versions: versions.into_iter().map(|v| { - v.encodable(&krate.name) - }).collect(), - keywords: kws.into_iter().map(|k| k.encodable()).collect(), - categories: cats.into_iter().map(|k| k.encodable()).collect(), - })) + Ok( + req.json( + &R { + krate: krate + .clone() + .encodable( + max_version, + Some(ids), + Some(&kws), + Some(&cats), + Some(badges), + false, + ), + versions: versions + .into_iter() + .map(|v| v.encodable(&krate.name)) + .collect(), + keywords: kws.into_iter().map(|k| k.encodable()).collect(), + categories: cats.into_iter().map(|k| k.encodable()).collect(), + } + ) + ) } /// Handles the `PUT /crates/new` route. @@ -874,113 +1017,125 @@ pub fn new(req: &mut Request) -> CargoResult { let name = &*new_crate.name; let vers = &*new_crate.vers; - let features = new_crate.features.iter().map(|(k, v)| { - (k[..].to_string(), v.iter().map(|v| v[..].to_string()).collect()) - }).collect::>>(); - let keywords = new_crate.keywords.as_ref().map(|kws| { - kws.iter().map(|kw| &**kw).collect() - }).unwrap_or_else(Vec::new); - - let categories = new_crate.categories.as_ref().map(|s| &s[..]) - .unwrap_or(&[]); + let features = new_crate + .features + .iter() + .map(|(k, v)| (k[..].to_string(), v.iter().map(|v| v[..].to_string()).collect())) + .collect::>>(); + let keywords = new_crate + .keywords + .as_ref() + .map(|kws| kws.iter().map(|kw| &**kw).collect()) + .unwrap_or_else(Vec::new); + + let categories = new_crate.categories.as_ref().map(|s| &s[..]).unwrap_or(&[]); let categories: Vec<_> = categories.iter().map(|k| &**k).collect(); let conn = req.db_conn()?; - conn.transaction(|| { - // Persist the new crate, if it doesn't already exist - let persist = NewCrate { - name: name, - description: new_crate.description.as_ref().map(|s| &**s), - homepage: new_crate.homepage.as_ref().map(|s| &**s), - documentation: new_crate.documentation.as_ref().map(|s| &**s), - readme: new_crate.readme.as_ref().map(|s| &**s), - repository: new_crate.repository.as_ref().map(|s| &**s), - license: new_crate.license.as_ref().map(|s| &**s), - max_upload_size: None, - }; - let license_file = new_crate.license_file.as_ref().map(|s| &**s); - let krate = persist.create_or_update(&conn, license_file, user.id)?; + conn.transaction( + || { + // Persist the new crate, if it doesn't already exist + let persist = NewCrate { + name: name, + description: new_crate.description.as_ref().map(|s| &**s), + homepage: new_crate.homepage.as_ref().map(|s| &**s), + documentation: new_crate.documentation.as_ref().map(|s| &**s), + readme: new_crate.readme.as_ref().map(|s| &**s), + repository: new_crate.repository.as_ref().map(|s| &**s), + license: new_crate.license.as_ref().map(|s| &**s), + max_upload_size: None, + }; + let license_file = new_crate.license_file.as_ref().map(|s| &**s); + let krate = persist.create_or_update(&conn, license_file, user.id)?; + + let owners = krate.owners(&conn)?; + if rights(req.app(), &owners, &user)? < Rights::Publish { + return Err( + human( + "crate name has already been claimed by \ + another user" + ) + ); + } - let owners = krate.owners(&conn)?; - if rights(req.app(), &owners, &user)? < Rights::Publish { - return Err(human("crate name has already been claimed by \ - another user")) - } + if krate.name != name { + return Err(human(&format_args!("crate was previously named `{}`", krate.name))); + } - if krate.name != name { - return Err(human(&format_args!("crate was previously named `{}`", krate.name))) - } + let length = req.content_length() + .chain_error(|| human("missing header: Content-Length"))?; + let max = krate + .max_upload_size + .map(|m| m as u64) + .unwrap_or(app.config.max_upload_size); + if length > max { + return Err(human(&format_args!("max upload size is: {}", max))); + } - let length = req.content_length().chain_error(|| { - human("missing header: Content-Length") - })?; - let max = krate.max_upload_size.map(|m| m as u64) - .unwrap_or(app.config.max_upload_size); - if length > max { - return Err(human(&format_args!("max upload size is: {}", max))) - } + // Persist the new version of this crate + let version = NewVersion::new(krate.id, vers, &features)? + .save(&conn, &new_crate.authors)?; + + // Link this new version to all dependencies + let git_deps = dependency::add_dependencies(&conn, &new_crate.deps, version.id)?; + + // Update all keywords for this crate + Keyword::update_crate(&conn, &krate, &keywords)?; + + // Update all categories for this crate, collecting any invalid categories + // in order to be able to warn about them + let ignored_invalid_categories = Category::update_crate(&conn, &krate, &categories)?; + + // Update all badges for this crate, collecting any invalid badges in + // order to be able to warn about them + let ignored_invalid_badges = Badge::update_crate(&conn, &krate, new_crate.badges.as_ref())?; + let max_version = krate.max_version(&conn)?; + + // Upload the crate, return way to delete the crate from the server + // If the git commands fail below, we shouldn't keep the crate on the + // server. + let (cksum, mut bomb) = app.config.uploader.upload(req, &krate, max, vers)?; + + // Register this crate in our local git repo. + let git_crate = git::Crate { + name: name.to_string(), + vers: vers.to_string(), + cksum: cksum.to_hex(), + features: features, + deps: git_deps, + yanked: Some(false), + }; + git::add_crate(&**req.app(), &git_crate) + .chain_error(|| internal(&format_args!("could not add crate `{}` to the git repo", name)))?; - // Persist the new version of this crate - let version = NewVersion::new(krate.id, vers, &features)? - .save(&conn, &new_crate.authors)?; - - // Link this new version to all dependencies - let git_deps = dependency::add_dependencies(&conn, &new_crate.deps, version.id)?; - - // Update all keywords for this crate - Keyword::update_crate(&conn, &krate, &keywords)?; - - // Update all categories for this crate, collecting any invalid categories - // in order to be able to warn about them - let ignored_invalid_categories = Category::update_crate(&conn, &krate, &categories)?; - - // Update all badges for this crate, collecting any invalid badges in - // order to be able to warn about them - let ignored_invalid_badges = Badge::update_crate( - &conn, - &krate, - new_crate.badges.as_ref() - )?; - let max_version = krate.max_version(&conn)?; - - // Upload the crate, return way to delete the crate from the server - // If the git commands fail below, we shouldn't keep the crate on the - // server. - let (cksum, mut bomb) = app.config.uploader.upload(req, &krate, max, vers)?; - - // Register this crate in our local git repo. - let git_crate = git::Crate { - name: name.to_string(), - vers: vers.to_string(), - cksum: cksum.to_hex(), - features: features, - deps: git_deps, - yanked: Some(false), - }; - git::add_crate(&**req.app(), &git_crate).chain_error(|| { - internal(&format_args!("could not add crate `{}` to the git repo", name)) - })?; + // Now that we've come this far, we're committed! + bomb.path = None; - // Now that we've come this far, we're committed! - bomb.path = None; + #[derive(RustcEncodable)] + struct Warnings<'a> { + invalid_categories: Vec<&'a str>, + invalid_badges: Vec<&'a str>, + } + let warnings = Warnings { + invalid_categories: ignored_invalid_categories, + invalid_badges: ignored_invalid_badges, + }; - #[derive(RustcEncodable)] - struct Warnings<'a> { - invalid_categories: Vec<&'a str>, - invalid_badges: Vec<&'a str>, + #[derive(RustcEncodable)] + struct R<'a> { + krate: EncodableCrate, + warnings: Warnings<'a>, + } + Ok( + req.json( + &R { + krate: krate.minimal_encodable(max_version, None, false), + warnings: warnings, + } + ) + ) } - let warnings = Warnings { - invalid_categories: ignored_invalid_categories, - invalid_badges: ignored_invalid_badges, - }; - - #[derive(RustcEncodable)] - struct R<'a> { krate: EncodableCrate, warnings: Warnings<'a> } - Ok(req.json(&R { - krate: krate.minimal_encodable(max_version, None, false), - warnings: warnings - })) - }) + ) } fn parse_new_headers(req: &mut Request) -> CargoResult<(upload::NewCrate, User)> { @@ -988,19 +1143,19 @@ fn parse_new_headers(req: &mut Request) -> CargoResult<(upload::NewCrate, User)> let amt = read_le_u32(req.body())? as u64; let max = req.app().config.max_upload_size; if amt > max { - return Err(human(&format_args!("max upload size is: {}", max))) + return Err(human(&format_args!("max upload size is: {}", max))); } let mut json = vec![0; amt as usize]; read_fill(req.body(), &mut json)?; - let json = String::from_utf8(json).map_err(|_| { - human("json body was not valid utf-8") - })?; - let new: upload::NewCrate = json::decode(&json).map_err(|e| { - human(&format_args!("invalid upload request: {:?}", e)) - })?; + let json = String::from_utf8(json) + .map_err(|_| human("json body was not valid utf-8"))?; + let new: upload::NewCrate = json::decode(&json) + .map_err(|e| human(&format_args!("invalid upload request: {:?}", e)))?; // Make sure required fields are provided - fn empty(s: Option<&String>) -> bool { s.map_or(true, |s| s.is_empty()) } + fn empty(s: Option<&String>) -> bool { + s.map_or(true, |s| s.is_empty()) + } let mut missing = Vec::new(); if empty(new.description.as_ref()) { @@ -1013,9 +1168,13 @@ fn parse_new_headers(req: &mut Request) -> CargoResult<(upload::NewCrate, User)> missing.push("authors"); } if !missing.is_empty() { - return Err(human(&format_args!("missing or empty metadata fields: {}. Please \ + return Err( + human( + &format_args!("missing or empty metadata fields: {}. Please \ see http://doc.crates.io/manifest.html#package-metadata for \ - how to upload metadata", missing.join(", ")))); + how to upload metadata", missing.join(", ")) + ) + ); } let user = req.user()?; @@ -1037,15 +1196,18 @@ pub fn download(req: &mut Request) -> CargoResult { increment_download_counts(req, crate_name, version)?; } - let redirect_url = req.app().config.uploader - .crate_location(crate_name, version).ok_or_else(|| - human("crate files not found") - )?; + let redirect_url = req.app() + .config + .uploader + .crate_location(crate_name, version) + .ok_or_else(|| human("crate files not found"))?; if req.wants_json() { #[derive(RustcEncodable)] - struct R { url: String } - Ok(req.json(&R{ url: redirect_url })) + struct R { + url: String, + } + Ok(req.json(&R { url: redirect_url })) } else { Ok(req.redirect(redirect_url)) } @@ -1055,7 +1217,8 @@ fn increment_download_counts(req: &Request, crate_name: &str, version: &str) -> use self::versions::dsl::*; let conn = req.db_conn()?; - let version_id = versions.select(id) + let version_id = versions + .select(id) .filter(crate_id.eq_any(Crate::by_name(crate_name).select(crates::id))) .filter(num.eq(version)) .first(&*conn)?; @@ -1094,13 +1257,28 @@ pub fn downloads(req: &mut Request) -> CargoResult { .load::(&*conn)?; #[derive(RustcEncodable, Queryable)] - struct ExtraDownload { date: String, downloads: i64 } + struct ExtraDownload { + date: String, + downloads: i64, + } #[derive(RustcEncodable)] - struct R { version_downloads: Vec, meta: Meta } + struct R { + version_downloads: Vec, + meta: Meta, + } #[derive(RustcEncodable)] - struct Meta { extra_downloads: Vec } + struct Meta { + extra_downloads: Vec, + } let meta = Meta { extra_downloads: extra }; - Ok(req.json(&R{ version_downloads: downloads, meta: meta })) + Ok( + req.json( + &R { + version_downloads: downloads, + meta: meta, + } + ) + ) } #[derive(Insertable, Queryable, Identifiable, Associations)] @@ -1116,13 +1294,13 @@ fn follow_target(req: &mut Request) -> CargoResult { let user = req.user()?; let conn = req.db_conn()?; let crate_name = &req.params()["crate_id"]; - let crate_id = Crate::by_name(crate_name) - .select(crates::id) - .first(&*conn)?; - Ok(Follow { - user_id: user.id, - crate_id: crate_id, - }) + let crate_id = Crate::by_name(crate_name).select(crates::id).first(&*conn)?; + Ok( + Follow { + user_id: user.id, + crate_id: crate_id, + } + ) } /// Handles the `PUT /crates/:crate_id/follow` route. @@ -1133,7 +1311,9 @@ pub fn follow(req: &mut Request) -> CargoResult { .into(follows::table) .execute(&*conn)?; #[derive(RustcEncodable)] - struct R { ok: bool } + struct R { + ok: bool, + } Ok(req.json(&R { ok: true })) } @@ -1143,7 +1323,9 @@ pub fn unfollow(req: &mut Request) -> CargoResult { let conn = req.db_conn()?; diesel::delete(&follow).execute(&*conn)?; #[derive(RustcEncodable)] - struct R { ok: bool } + struct R { + ok: bool, + } Ok(req.json(&R { ok: true })) } @@ -1156,7 +1338,9 @@ pub fn following(req: &mut Request) -> CargoResult { let following = diesel::select(exists(follows::table.find(follow.id()))) .get_result(&*conn)?; #[derive(RustcEncodable)] - struct R { following: bool } + struct R { + following: bool, + } Ok(req.json(&R { following: following })) } @@ -1168,12 +1352,16 @@ pub fn versions(req: &mut Request) -> CargoResult { let tx = req.tx()?; let krate = Crate::find_by_name(tx, crate_name)?; let versions = krate.versions(tx)?; - let versions = versions.into_iter().map(|v| v.encodable(crate_name)) - .collect(); + let versions = versions + .into_iter() + .map(|v| v.encodable(crate_name)) + .collect(); #[derive(RustcEncodable)] - struct R { versions: Vec } - Ok(req.json(&R{ versions: versions })) + struct R { + versions: Vec, + } + Ok(req.json(&R { versions: versions })) } /// Handles the `GET /crates/:crate_id/owners` route. @@ -1181,14 +1369,17 @@ pub fn owners(req: &mut Request) -> CargoResult { let crate_name = &req.params()["crate_id"]; let conn = req.db_conn()?; let krate = Crate::by_name(crate_name).first::(&*conn)?; - let owners = krate.owners(&conn)? + let owners = krate + .owners(&conn)? .into_iter() .map(Owner::encodable) .collect(); #[derive(RustcEncodable)] - struct R { users: Vec } - Ok(req.json(&R{ users: owners })) + struct R { + users: Vec, + } + Ok(req.json(&R { users: owners })) } /// Handles the `PUT /crates/:crate_id/owners` route. @@ -1227,33 +1418,35 @@ fn modify_owners(req: &mut Request, add: bool) -> CargoResult { owners: Option>, } - let request: Request = json::decode(&body).map_err(|_| { - human("invalid json request") - })?; + let request: Request = json::decode(&body) + .map_err(|_| human("invalid json request"))?; - let logins = request.owners.or(request.users).ok_or_else(|| { - human("invalid json request") - })?; + let logins = request + .owners + .or(request.users) + .ok_or_else(|| human("invalid json request"))?; for login in &logins { if add { if owners.iter().any(|owner| owner.login() == *login) { - return Err(human(&format_args!("`{}` is already an owner", login))) + return Err(human(&format_args!("`{}` is already an owner", login))); } krate.owner_add(req.app(), &conn, user, login)?; } else { // Removing the team that gives you rights is prevented because // team members only have Rights::Publish if *login == user.gh_login { - return Err(human("cannot remove yourself as an owner")) + return Err(human("cannot remove yourself as an owner")); } krate.owner_remove(&conn, user, login)?; } } #[derive(RustcEncodable)] - struct R { ok: bool } - Ok(req.json(&R{ ok: true })) + struct R { + ok: bool, + } + Ok(req.json(&R { ok: true })) } /// Handles the `GET /crates/:crate_id/reverse_dependencies` route. @@ -1263,15 +1456,28 @@ pub fn reverse_dependencies(req: &mut Request) -> CargoResult { let krate = Crate::find_by_name(conn, name)?; let (offset, limit) = req.pagination(10, 100)?; let (rev_deps, total) = krate.reverse_dependencies(conn, offset, limit)?; - let rev_deps = rev_deps.into_iter() + let rev_deps = rev_deps + .into_iter() .map(ReverseDependency::encodable) .collect(); #[derive(RustcEncodable)] - struct R { dependencies: Vec, meta: Meta } + struct R { + dependencies: Vec, + meta: Meta, + } #[derive(RustcEncodable)] - struct Meta { total: i64 } - Ok(req.json(&R{ dependencies: rev_deps, meta: Meta { total: total } })) + struct Meta { + total: i64, + } + Ok( + req.json( + &R { + dependencies: rev_deps, + meta: Meta { total: total }, + } + ) + ) } use diesel::types::{Text, Date}; diff --git a/src/lib.rs b/src/lib.rs index 25cf755e746..a2ebbe6fc8b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,11 +7,16 @@ #![cfg_attr(feature = "clippy", feature(plugin))] #![cfg_attr(feature = "clippy", plugin(clippy))] -#[macro_use] extern crate diesel; -#[macro_use] extern crate diesel_codegen; -#[macro_use] extern crate log; -#[macro_use] extern crate serde_json; -#[macro_use] extern crate serde_derive; +#[macro_use] +extern crate diesel; +#[macro_use] +extern crate diesel_codegen; +#[macro_use] +extern crate log; +#[macro_use] +extern crate serde_json; +#[macro_use] +extern crate serde_derive; extern crate chrono; extern crate curl; extern crate diesel_full_text_search; @@ -109,8 +114,14 @@ pub fn middleware(app: Arc) -> MiddlewareBuilder { api_router.put("/crates/new", C(krate::new)); api_router.get("/crates/:crate_id/:version", C(version::show)); api_router.get("/crates/:crate_id/:version/download", C(krate::download)); - api_router.get("/crates/:crate_id/:version/dependencies", C(version::dependencies)); - api_router.get("/crates/:crate_id/:version/downloads", C(version::downloads)); + api_router.get( + "/crates/:crate_id/:version/dependencies", + C(version::dependencies), + ); + api_router.get( + "/crates/:crate_id/:version/downloads", + C(version::downloads), + ); api_router.get("/crates/:crate_id/:version/authors", C(version::authors)); api_router.get("/crates/:crate_id/downloads", C(krate::downloads)); api_router.get("/crates/:crate_id/versions", C(krate::versions)); @@ -122,7 +133,10 @@ pub fn middleware(app: Arc) -> MiddlewareBuilder { api_router.delete("/crates/:crate_id/owners", C(krate::remove_owners)); api_router.delete("/crates/:crate_id/:version/yank", C(version::yank)); api_router.put("/crates/:crate_id/:version/unyank", C(version::unyank)); - api_router.get("/crates/:crate_id/reverse_dependencies", C(krate::reverse_dependencies)); + api_router.get( + "/crates/:crate_id/reverse_dependencies", + C(krate::reverse_dependencies), + ); api_router.get("/versions", C(version::index)); api_router.get("/versions/:version_id", C(version::show)); api_router.get("/keywords", C(keyword::index)); @@ -169,8 +183,7 @@ pub fn middleware(app: Arc) -> MiddlewareBuilder { m.around(util::Head::default()); m.add(conduit_conditional_get::ConditionalGet); m.add(conduit_cookie::Middleware::new(app.session_key.as_bytes())); - m.add(conduit_cookie::SessionMiddleware::new("cargo_session", - env == Env::Production)); + m.add(conduit_cookie::SessionMiddleware::new("cargo_session", env == Env::Production)); m.add(app::AppMiddleware::new(app)); if env != Env::Test { m.add(db::TransactionMiddleware); @@ -185,8 +198,7 @@ pub fn middleware(app: Arc) -> MiddlewareBuilder { struct DebugMiddleware; impl conduit_middleware::Middleware for DebugMiddleware { - fn before(&self, req: &mut conduit::Request) - -> Result<(), Box> { + fn before(&self, req: &mut conduit::Request) -> Result<(), Box> { println!(" version: {}", req.http_version()); println!(" method: {:?}", req.method()); println!(" scheme: {:?}", req.scheme()); @@ -199,16 +211,20 @@ pub fn middleware(app: Arc) -> MiddlewareBuilder { } Ok(()) } - fn after(&self, _req: &mut conduit::Request, - res: Result>) - -> Result> { - res.map(|res| { - println!(" <- {:?}", res.status); - for (k, v) in &res.headers { - println!(" <- {} {:?}", k, v); + fn after( + &self, + _req: &mut conduit::Request, + res: Result>, + ) -> Result> { + res.map( + |res| { + println!(" <- {:?}", res.status); + for (k, v) in &res.headers { + println!(" <- {} {:?}", k, v); + } + res } - res - }) + ) } } } @@ -223,9 +239,7 @@ pub fn encode_time(ts: time::Timespec) -> String { pub fn env(s: &str) -> String { dotenv::dotenv().ok(); - ::std::env::var(s).unwrap_or_else(|_| { - panic!("must have `{}` defined", s) - }) + ::std::env::var(s).unwrap_or_else(|_| panic!("must have `{}` defined", s)) } sql_function!(lower, lower_t, (x: ::diesel::types::Text) -> ::diesel::types::Text); diff --git a/src/owner.rs b/src/owner.rs index 70faa2d0987..898e8fb0c49 100644 --- a/src/owner.rs +++ b/src/owner.rs @@ -50,7 +50,6 @@ pub struct Team { /// Sugary goodness pub name: Option, pub avatar: Option, - } #[derive(RustcEncodable)] @@ -75,11 +74,7 @@ pub enum Rights { impl Team { /// Tries to create the Team in the DB (assumes a `:` has already been found). - pub fn create(app: &App, - conn: &PgConnection, - login: &str, - req_user: &User) - -> CargoResult { + pub fn create(app: &App, conn: &PgConnection, login: &str, req_user: &User) -> CargoResult { // must look like system:xxxxxxx let mut chunks = login.split(':'); match chunks.next().unwrap() { @@ -87,15 +82,25 @@ impl Team { "github" => { // Ok to unwrap since we know one ":" is contained let org = chunks.next().unwrap(); - let team = chunks.next().ok_or_else(|| - human("missing github team argument; \ - format is github:org:team") - )?; + let team = chunks + .next() + .ok_or_else( + || { + human( + "missing github team argument; \ + format is github:org:team" + ) + } + )?; Team::create_github_team(app, conn, login, org, team, req_user) } _ => { - Err(human("unknown organization handler, \ - only 'github:org:team' is supported")) + Err( + human( + "unknown organization handler, \ + only 'github:org:team' is supported" + ) + ) } } } @@ -103,9 +108,14 @@ impl Team { /// Tries to create a Github Team from scratch. Assumes `org` and `team` are /// correctly parsed out of the full `name`. `name` is passed as a /// convenience to avoid rebuilding it. - pub fn create_github_team(app: &App, conn: &PgConnection, login: &str, - org_name: &str, team_name: &str, req_user: &User) - -> CargoResult { + pub fn create_github_team( + app: &App, + conn: &PgConnection, + login: &str, + org_name: &str, + team_name: &str, + req_user: &User, + ) -> CargoResult { // GET orgs/:org/teams // check that `team` is the `slug` in results, and grab its data @@ -113,20 +123,24 @@ impl Team { fn whitelist(c: &char) -> bool { match *c { 'a'...'z' | 'A'...'Z' | '0'...'9' | '-' | '_' => false, - _ => true + _ => true, } } if let Some(c) = org_name.chars().find(whitelist) { - return Err(human(&format_args!("organization cannot contain special \ - characters like {}", c))); + return Err( + human( + &format_args!("organization cannot contain special \ + characters like {}", c) + ) + ); } #[derive(RustcDecodable)] struct GithubTeam { - slug: String, // the name we want to find - id: i32, // unique GH id (needed for membership queries) - name: Option, // Pretty name + slug: String, // the name we want to find + id: i32, // unique GH id (needed for membership queries) + name: Option, // Pretty name } // FIXME: we just set per_page=100 and don't bother chasing pagination @@ -136,11 +150,17 @@ impl Team { let (handle, data) = http::github(app, &url, &token)?; let teams: Vec = http::parse_github_response(handle, &data)?; - let team = teams.into_iter().find(|team| team.slug == team_name) - .ok_or_else(|| { - human(&format_args!("could not find the github team {}/{}", - org_name, team_name)) - })?; + let team = teams + .into_iter() + .find(|team| team.slug == team_name) + .ok_or_else( + || { + human( + &format_args!("could not find the github team {}/{}", + org_name, team_name) + ) + } + )?; if !team_with_gh_id_contains_user(app, team.id, req_user)? { return Err(human("only members of a team can add it as an owner")); @@ -158,12 +178,7 @@ impl Team { Team::insert(conn, login, team.id, team.name, org.avatar_url) } - pub fn insert(conn: &PgConnection, - login: &str, - github_id: i32, - name: Option, - avatar: Option) - -> CargoResult { + pub fn insert(conn: &PgConnection, login: &str, github_id: i32, name: Option, avatar: Option) -> CargoResult { use diesel::pg::upsert::*; #[derive(Insertable, AsChangeset)] @@ -181,9 +196,8 @@ impl Team { avatar: avatar, }; - diesel::insert( - &new_team.on_conflict(teams::github_id, do_update().set(&new_team)) - ).into(teams::table) + diesel::insert(&new_team.on_conflict(teams::github_id, do_update().set(&new_team))) + .into(teams::table) .get_result(conn) .map_err(Into::into) } @@ -197,8 +211,7 @@ impl Team { } } -fn team_with_gh_id_contains_user(app: &App, github_id: i32, user: &User) - -> CargoResult { +fn team_with_gh_id_contains_user(app: &App, github_id: i32, user: &User) -> CargoResult { // GET teams/:team_id/memberships/:user_name // check that "state": "active" @@ -214,7 +227,7 @@ fn team_with_gh_id_contains_user(app: &App, github_id: i32, user: &User) // Officially how `false` is returned if handle.response_code().unwrap() == 404 { - return Ok(false) + return Ok(false); } let membership: Membership = http::parse_github_response(handle, &resp)?; @@ -235,29 +248,28 @@ impl Model for Team { } } - fn table_name(_: Option) -> &'static str { "teams" } + fn table_name(_: Option) -> &'static str { + "teams" + } } impl Owner { /// Finds the owner by name, failing out if it doesn't exist. /// May be a user's GH login, or a full team name. This is case /// sensitive. - pub fn find_by_login(conn: &PgConnection, - name: &str) -> CargoResult { + pub fn find_by_login(conn: &PgConnection, name: &str) -> CargoResult { if name.contains(':') { - teams::table.filter(teams::login.eq(name)) + teams::table + .filter(teams::login.eq(name)) .first(conn) .map(Owner::Team) - .map_err(|_| - human(&format_args!("could not find team with name {}", name)) - ) + .map_err(|_| human(&format_args!("could not find team with name {}", name))) } else { - users::table.filter(users::gh_login.eq(name)) + users::table + .filter(users::gh_login.eq(name)) .first(conn) .map(Owner::User) - .map_err(|_| - human(&format_args!("could not find user with login `{}`", name)) - ) + .map_err(|_| human(&format_args!("could not find user with login `{}`", name))) } } @@ -284,7 +296,14 @@ impl Owner { pub fn encodable(self) -> EncodableOwner { match self { - Owner::User(User { id, email, name, gh_login, gh_avatar, .. }) => { + Owner::User(User { + id, + email, + name, + gh_login, + gh_avatar, + .. + }) => { let url = format!("https://github.com/{}", gh_login); EncodableOwner { id: id, @@ -296,7 +315,13 @@ impl Owner { kind: String::from("user"), } } - Owner::Team(Team { id, name, login, avatar, .. }) => { + Owner::Team(Team { + id, + name, + login, + avatar, + .. + }) => { let url = { let mut parts = login.split(':'); parts.next(); // discard github @@ -329,14 +354,17 @@ pub fn rights(app: &App, owners: &[Owner], user: &User) -> CargoResult { let mut best = Rights::None; for owner in owners { match *owner { - Owner::User(ref other_user) => if other_user.id == user.id { - return Ok(Rights::Full); - }, - Owner::Team(ref team) => if team.contains_user(app, user)? { - best = Rights::Publish; - }, + Owner::User(ref other_user) => { + if other_user.id == user.id { + return Ok(Rights::Full); + } + } + Owner::Team(ref team) => { + if team.contains_user(app, user)? { + best = Rights::Publish; + } + } } } Ok(best) } - diff --git a/src/tests/all.rs b/src/tests/all.rs index ce5fe12452e..ad411786b46 100755 --- a/src/tests/all.rs +++ b/src/tests/all.rs @@ -68,9 +68,13 @@ macro_rules! bad_resp { } #[derive(RustcDecodable, Debug)] -struct Error { detail: String } +struct Error { + detail: String, +} #[derive(RustcDecodable)] -struct Bad { errors: Vec } +struct Bad { + errors: Vec, +} mod badge; mod category; @@ -93,11 +97,13 @@ fn app() -> (record::Bomb, Arc, conduit_middleware::MiddlewareBuilder) { let api_protocol = String::from("http"); let uploader = cargo_registry::Uploader::S3 { - bucket: s3::Bucket::new(String::from("alexcrichton-test"), - None, - String::new(), - String::new(), - &api_protocol), + bucket: s3::Bucket::new( + String::from("alexcrichton-test"), + None, + String::new(), + String::new(), + &api_protocol, + ), proxy: Some(proxy), }; @@ -139,7 +145,9 @@ fn ok_resp(r: &conduit::Response) -> bool { fn bad_resp(r: &mut conduit::Response) -> Option { let bad = json::(r); - if bad.errors.len() == 0 { return None } + if bad.errors.len() == 0 { + return None; + } Some(bad) } @@ -154,26 +162,27 @@ fn json(r: &mut conduit::Response) -> T { let j = fixup(j); let s = j.to_string(); return match json::decode(&s) { - Ok(t) => t, - Err(e) => panic!("failed to decode: {:?}\n{}", e, s), - }; + Ok(t) => t, + Err(e) => panic!("failed to decode: {:?}\n{}", e, s), + }; fn fixup(json: Json) -> Json { match json { Json::Object(object) => { - Json::Object(object.into_iter().map(|(k, v)| { - let k = if k == "crate" { - "krate".to_string() - } else { - k - }; - (k, fixup(v)) - }).collect()) - } - Json::Array(list) => { - Json::Array(list.into_iter().map(fixup).collect()) + Json::Object( + object + .into_iter() + .map( + |(k, v)| { + let k = if k == "crate" { "krate".to_string() } else { k }; + (k, fixup(v)) + } + ) + .collect() + ) } + Json::Array(list) => Json::Array(list.into_iter().map(fixup).collect()), j => j, } } @@ -262,9 +271,11 @@ impl<'a> CrateBuilder<'a> { } fn version(mut self, version: &str) -> Self { - let version = semver::Version::parse(version).unwrap_or_else(|e| { - panic!("The version {} is not valid: {}", version, e); - }); + let version = semver::Version::parse(version).unwrap_or_else( + |e| { + panic!("The version {} is not valid: {}", version, e); + } + ); self.versions.push(version); self } @@ -288,12 +299,13 @@ impl<'a> CrateBuilder<'a> { } if self.versions.is_empty() { - self.versions.push("0.99.0".parse().expect("invalid version number")); + self.versions + .push("0.99.0".parse().expect("invalid version number")); } for version_num in &self.versions { NewVersion::new(krate.id, version_num, &HashMap::new())? - .save(connection, &[])?; + .save(connection, &[])?; } if !self.keywords.is_empty() { @@ -306,9 +318,11 @@ impl<'a> CrateBuilder<'a> { fn expect_build(self, connection: &PgConnection) -> Crate { let name = self.krate.name; self.build(connection) - .unwrap_or_else(|e| { - panic!("Unable to create crate {}: {:?}", name, e); - }) + .unwrap_or_else( + |e| { + panic!("Unable to create crate {}: {:?}", name, e); + } + ) } } @@ -335,13 +349,16 @@ fn krate(name: &str) -> Crate { } fn mock_user(req: &mut Request, u: User) -> User { - let u = User::find_or_insert(req.tx().unwrap(), - u.gh_id, - &u.gh_login, - u.email.as_ref().map(|s| &s[..]), - u.name.as_ref().map(|s| &s[..]), - u.gh_avatar.as_ref().map(|s| &s[..]), - &u.gh_access_token).unwrap(); + let u = User::find_or_insert( + req.tx().unwrap(), + u.gh_id, + &u.gh_login, + u.email.as_ref().map(|s| &s[..]), + u.name.as_ref().map(|s| &s[..]), + u.gh_avatar.as_ref().map(|s| &s[..]), + &u.gh_access_token, + ) + .unwrap(); sign_in_as(req, &u); return u; } @@ -360,18 +377,22 @@ fn mock_crate(req: &mut Request, krate: Crate) -> (Crate, Version) { mock_crate_vers(req, krate, &semver::Version::parse("1.0.0").unwrap()) } -fn mock_crate_vers(req: &mut Request, krate: Crate, v: &semver::Version) - -> (Crate, Version) { +fn mock_crate_vers(req: &mut Request, krate: Crate, v: &semver::Version) -> (Crate, Version) { let user = req.extensions().find::().unwrap(); - let mut krate = Crate::find_or_insert(req.tx().unwrap(), &krate.name, - user.id, &krate.description, - &krate.homepage, - &krate.documentation, - &krate.readme, - &krate.repository, - &krate.license, - &None, - krate.max_upload_size).unwrap(); + let mut krate = Crate::find_or_insert( + req.tx().unwrap(), + &krate.name, + user.id, + &krate.description, + &krate.homepage, + &krate.documentation, + &krate.readme, + &krate.repository, + &krate.license, + &None, + krate.max_upload_size, + ) + .unwrap(); let v = krate.add_version(req.tx().unwrap(), v, &HashMap::new(), &[]); (krate, v.unwrap()) } @@ -387,30 +408,44 @@ fn new_dependency(conn: &PgConnection, version: &Version, krate: &Crate) -> Depe optional: false, ..Default::default() }; - insert(&dep).into(dependencies::table).get_result(conn).unwrap() -} - -fn mock_dep(req: &mut Request, version: &Version, krate: &Crate, - target: Option<&str>) -> Dependency { - Dependency::insert(req.tx().unwrap(), - version.id, - krate.id, - &semver::VersionReq::parse(">= 0").unwrap(), - Kind::Normal, - false, true, &[], - &target.map(|s| s.to_string())).unwrap() + insert(&dep) + .into(dependencies::table) + .get_result(conn) + .unwrap() +} + +fn mock_dep(req: &mut Request, version: &Version, krate: &Crate, target: Option<&str>) -> Dependency { + Dependency::insert( + req.tx().unwrap(), + version.id, + krate.id, + &semver::VersionReq::parse(">= 0").unwrap(), + Kind::Normal, + false, + true, + &[], + &target.map(|s| s.to_string()), + ) + .unwrap() } fn new_category<'a>(category: &'a str, slug: &'a str) -> NewCategory<'a> { - NewCategory { category: category, slug: slug, ..NewCategory::default() } + NewCategory { + category: category, + slug: slug, + ..NewCategory::default() + } } fn mock_category(req: &mut Request, name: &str, slug: &str) -> Category { let conn = req.tx().unwrap(); - let stmt = conn.prepare(" \ + let stmt = conn.prepare( + " \ INSERT INTO categories (category, slug) \ VALUES ($1, $2) \ - RETURNING *").unwrap(); + RETURNING *" + ) + .unwrap(); let rows = stmt.query(&[&name, &slug]).unwrap(); Model::from_row(&rows.iter().next().unwrap()) } @@ -419,11 +454,7 @@ fn logout(req: &mut Request) { req.mut_extensions().pop::(); } -fn request_with_user_and_mock_crate( - app: &Arc, - user: NewUser, - krate: &str, -) -> MockRequest { +fn request_with_user_and_mock_crate(app: &Arc, user: NewUser, krate: &str) -> MockRequest { let mut req = new_req(app.clone(), krate, "1.0.0"); { let conn = app.diesel_database.get().unwrap(); @@ -438,89 +469,95 @@ fn new_req(app: Arc, krate: &str, version: &str) -> MockRequest { new_req_full(app, ::krate(krate), version, Vec::new()) } -fn new_req_full(app: Arc, krate: Crate, version: &str, - deps: Vec) -> MockRequest { +fn new_req_full(app: Arc, krate: Crate, version: &str, deps: Vec) -> MockRequest { let mut req = ::req(app, Method::Put, "/api/v1/crates/new"); - req.with_body(&new_req_body( - krate, version, deps, Vec::new(), Vec::new(), HashMap::new() - )); + req.with_body(&new_req_body(krate, version, deps, Vec::new(), Vec::new(), HashMap::new())); return req; } -fn new_req_with_keywords(app: Arc, krate: Crate, version: &str, - kws: Vec) -> MockRequest { +fn new_req_with_keywords(app: Arc, krate: Crate, version: &str, kws: Vec) -> MockRequest { let mut req = ::req(app, Method::Put, "/api/v1/crates/new"); - req.with_body(&new_req_body( - krate, version, Vec::new(), kws, Vec::new(), HashMap::new() - )); + req.with_body(&new_req_body(krate, version, Vec::new(), kws, Vec::new(), HashMap::new())); return req; } -fn new_req_with_categories(app: Arc, krate: Crate, version: &str, - cats: Vec) -> MockRequest { +fn new_req_with_categories(app: Arc, krate: Crate, version: &str, cats: Vec) -> MockRequest { let mut req = ::req(app, Method::Put, "/api/v1/crates/new"); - req.with_body(&new_req_body( - krate, version, Vec::new(), Vec::new(), cats, HashMap::new() - )); + req.with_body(&new_req_body(krate, version, Vec::new(), Vec::new(), cats, HashMap::new())); return req; } -fn new_req_with_badges(app: Arc, krate: Crate, version: &str, - badges: HashMap>) - -> MockRequest { +fn new_req_with_badges(app: Arc, krate: Crate, version: &str, badges: HashMap>) -> MockRequest { let mut req = ::req(app, Method::Put, "/api/v1/crates/new"); - req.with_body(&new_req_body( - krate, version, Vec::new(), Vec::new(), Vec::new(), badges - )); + req.with_body(&new_req_body(krate, version, Vec::new(), Vec::new(), Vec::new(), badges)); return req; } fn new_req_body_version_2(krate: Crate) -> Vec { new_req_body( - krate, "2.0.0", Vec::new(), Vec::new(), Vec::new(), HashMap::new() + krate, + "2.0.0", + Vec::new(), + Vec::new(), + Vec::new(), + HashMap::new(), ) } -fn new_req_body(krate: Crate, version: &str, deps: Vec, - kws: Vec, cats: Vec, - badges: HashMap>) -> Vec { +fn new_req_body( + krate: Crate, + version: &str, + deps: Vec, + kws: Vec, + cats: Vec, + badges: HashMap>, +) -> Vec { let kws = kws.into_iter().map(u::Keyword).collect(); let cats = cats.into_iter().map(u::Category).collect(); - new_crate_to_body(&u::NewCrate { - name: u::CrateName(krate.name), - vers: u::CrateVersion(semver::Version::parse(version).unwrap()), - features: HashMap::new(), - deps: deps, - authors: vec!["foo".to_string()], - description: Some("description".to_string()), - homepage: krate.homepage, - documentation: krate.documentation, - readme: krate.readme, - keywords: Some(u::KeywordList(kws)), - categories: Some(u::CategoryList(cats)), - license: Some("MIT".to_string()), - license_file: None, - repository: krate.repository, - badges: Some(badges), - }, &[]) + new_crate_to_body( + &u::NewCrate { + name: u::CrateName(krate.name), + vers: u::CrateVersion(semver::Version::parse(version).unwrap()), + features: HashMap::new(), + deps: deps, + authors: vec!["foo".to_string()], + description: Some("description".to_string()), + homepage: krate.homepage, + documentation: krate.documentation, + readme: krate.readme, + keywords: Some(u::KeywordList(kws)), + categories: Some(u::CategoryList(cats)), + license: Some("MIT".to_string()), + license_file: None, + repository: krate.repository, + badges: Some(badges), + }, + &[], + ) } fn new_crate_to_body(new_crate: &u::NewCrate, krate: &[u8]) -> Vec { let json = json::encode(&new_crate).unwrap(); let mut body = Vec::new(); - body.extend([ - (json.len() >> 0) as u8, - (json.len() >> 8) as u8, - (json.len() >> 16) as u8, - (json.len() >> 24) as u8, - ].iter().cloned()); + body.extend( + [ + (json.len() >> 0) as u8, + (json.len() >> 8) as u8, + (json.len() >> 16) as u8, + (json.len() >> 24) as u8, + ] + .iter() + .cloned() + ); body.extend(json.as_bytes().iter().cloned()); - body.extend(&[ - (krate.len() >> 0) as u8, - (krate.len() >> 8) as u8, - (krate.len() >> 16) as u8, - (krate.len() >> 24) as u8, - ]); + body.extend( + &[ + (krate.len() >> 0) as u8, + (krate.len() >> 8) as u8, + (krate.len() >> 16) as u8, + (krate.len() >> 24) as u8, + ] + ); body.extend(krate); body } diff --git a/src/tests/badge.rs b/src/tests/badge.rs index df997918390..e97b812a166 100644 --- a/src/tests/badge.rs +++ b/src/tests/badge.rs @@ -27,11 +27,8 @@ fn set_up() -> (Arc, Crate, BadgeRef) { let krate = { let conn = app.diesel_database.get().unwrap(); - let u = ::new_user("foo") - .create_or_update(&conn) - .unwrap(); - ::CrateBuilder::new("badged_crate", u.id) - .expect_build(&conn) + let u = ::new_user("foo").create_or_update(&conn).unwrap(); + ::CrateBuilder::new("badged_crate", u.id).expect_build(&conn) }; let appveyor = Badge::Appveyor { @@ -40,60 +37,32 @@ fn set_up() -> (Arc, Crate, BadgeRef) { repository: String::from("rust-lang/cargo"), }; let mut badge_attributes_appveyor = HashMap::new(); - badge_attributes_appveyor.insert( - String::from("service"), - String::from("github") - ); - badge_attributes_appveyor.insert( - String::from("repository"), - String::from("rust-lang/cargo") - ); + badge_attributes_appveyor.insert(String::from("service"), String::from("github")); + badge_attributes_appveyor.insert(String::from("repository"), String::from("rust-lang/cargo")); let travis_ci = Badge::TravisCi { branch: Some(String::from("beta")), repository: String::from("rust-lang/rust"), }; let mut badge_attributes_travis_ci = HashMap::new(); - badge_attributes_travis_ci.insert( - String::from("branch"), - String::from("beta") - ); - badge_attributes_travis_ci.insert( - String::from("repository"), - String::from("rust-lang/rust") - ); + badge_attributes_travis_ci.insert(String::from("branch"), String::from("beta")); + badge_attributes_travis_ci.insert(String::from("repository"), String::from("rust-lang/rust")); let gitlab = Badge::GitLab { branch: Some(String::from("beta")), repository: String::from("rust-lang/rust"), }; let mut badge_attributes_gitlab = HashMap::new(); - badge_attributes_gitlab.insert( - String::from("branch"), - String::from("beta") - ); - badge_attributes_gitlab.insert( - String::from("repository"), - String::from("rust-lang/rust") - ); + badge_attributes_gitlab.insert(String::from("branch"), String::from("beta")); + badge_attributes_gitlab.insert(String::from("repository"), String::from("rust-lang/rust")); - let isitmaintained_issue_resolution = Badge::IsItMaintainedIssueResolution { - repository: String::from("rust-lang/rust"), - }; + let isitmaintained_issue_resolution = Badge::IsItMaintainedIssueResolution { repository: String::from("rust-lang/rust") }; let mut badge_attributes_isitmaintained_issue_resolution = HashMap::new(); - badge_attributes_isitmaintained_issue_resolution.insert( - String::from("repository"), - String::from("rust-lang/rust") - ); + badge_attributes_isitmaintained_issue_resolution.insert(String::from("repository"), String::from("rust-lang/rust")); - let isitmaintained_open_issues = Badge::IsItMaintainedOpenIssues { - repository: String::from("rust-lang/rust"), - }; + let isitmaintained_open_issues = Badge::IsItMaintainedOpenIssues { repository: String::from("rust-lang/rust") }; let mut badge_attributes_isitmaintained_open_issues = HashMap::new(); - badge_attributes_isitmaintained_open_issues.insert( - String::from("repository"), - String::from("rust-lang/rust") - ); + badge_attributes_isitmaintained_open_issues.insert(String::from("repository"), String::from("rust-lang/rust")); let codecov = Badge::Codecov { service: Some(String::from("github")), @@ -101,18 +70,9 @@ fn set_up() -> (Arc, Crate, BadgeRef) { repository: String::from("rust-lang/rust"), }; let mut badge_attributes_codecov = HashMap::new(); - badge_attributes_codecov.insert( - String::from("branch"), - String::from("beta") - ); - badge_attributes_codecov.insert( - String::from("repository"), - String::from("rust-lang/rust") - ); - badge_attributes_codecov.insert( - String::from("service"), - String::from("github") - ); + badge_attributes_codecov.insert(String::from("branch"), String::from("beta")); + badge_attributes_codecov.insert(String::from("repository"), String::from("rust-lang/rust")); + badge_attributes_codecov.insert(String::from("service"), String::from("github")); let coveralls = Badge::Coveralls { service: Some(String::from("github")), @@ -120,18 +80,9 @@ fn set_up() -> (Arc, Crate, BadgeRef) { repository: String::from("rust-lang/rust"), }; let mut badge_attributes_coveralls = HashMap::new(); - badge_attributes_coveralls.insert( - String::from("branch"), - String::from("beta") - ); - badge_attributes_coveralls.insert( - String::from("repository"), - String::from("rust-lang/rust") - ); - badge_attributes_coveralls.insert( - String::from("service"), - String::from("github") - ); + badge_attributes_coveralls.insert(String::from("branch"), String::from("beta")); + badge_attributes_coveralls.insert(String::from("repository"), String::from("rust-lang/rust")); + badge_attributes_coveralls.insert(String::from("service"), String::from("github")); let badges = BadgeRef { appveyor: appveyor, @@ -170,10 +121,7 @@ fn update_add_appveyor() { let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); - badges.insert( - String::from("appveyor"), - test_badges.appveyor_attributes - ); + badges.insert(String::from("appveyor"), test_badges.appveyor_attributes); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.appveyor]); } @@ -185,10 +133,7 @@ fn update_add_travis_ci() { let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); - badges.insert( - String::from("travis-ci"), - test_badges.travis_ci_attributes - ); + badges.insert(String::from("travis-ci"), test_badges.travis_ci_attributes); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.travis_ci]); } @@ -200,10 +145,7 @@ fn update_add_gitlab() { let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); - badges.insert( - String::from("gitlab"), - test_badges.gitlab_attributes - ); + badges.insert(String::from("gitlab"), test_badges.gitlab_attributes); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.gitlab]); } @@ -217,10 +159,13 @@ fn update_add_isitmaintained_issue_resolution() { let mut badges = HashMap::new(); badges.insert( String::from("is-it-maintained-issue-resolution"), - test_badges.isitmaintained_issue_resolution_attributes + test_badges.isitmaintained_issue_resolution_attributes, ); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); - assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.isitmaintained_issue_resolution]); + assert_eq!( + krate.badges(&conn).unwrap(), + vec![test_badges.isitmaintained_issue_resolution] + ); } #[test] @@ -232,10 +177,13 @@ fn update_add_isitmaintained_open_issues() { let mut badges = HashMap::new(); badges.insert( String::from("is-it-maintained-open-issues"), - test_badges.isitmaintained_open_issues_attributes + test_badges.isitmaintained_open_issues_attributes, ); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); - assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.isitmaintained_open_issues]); + assert_eq!( + krate.badges(&conn).unwrap(), + vec![test_badges.isitmaintained_open_issues] + ); } #[test] @@ -245,10 +193,7 @@ fn update_add_codecov() { let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); - badges.insert( - String::from("codecov"), - test_badges.codecov_attributes - ); + badges.insert(String::from("codecov"), test_badges.codecov_attributes); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.codecov]); } @@ -260,10 +205,7 @@ fn update_add_coveralls() { let conn = app.diesel_database.get().unwrap(); let mut badges = HashMap::new(); - badges.insert( - String::from("coveralls"), - test_badges.coveralls_attributes - ); + badges.insert(String::from("coveralls"), test_badges.coveralls_attributes); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.coveralls]); } @@ -276,10 +218,7 @@ fn replace_badge() { // Add a badge let mut badges = HashMap::new(); - badges.insert( - String::from("gitlab"), - test_badges.gitlab_attributes - ); + badges.insert(String::from("gitlab"), test_badges.gitlab_attributes); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.gitlab]); @@ -287,7 +226,7 @@ fn replace_badge() { badges.clear(); badges.insert( String::from("travis-ci"), - test_badges.travis_ci_attributes.clone() + test_badges.travis_ci_attributes.clone(), ); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.travis_ci]); @@ -301,10 +240,7 @@ fn update_attributes() { // Add a travis-ci badge let mut badges = HashMap::new(); - badges.insert( - String::from("travis-ci"), - test_badges.travis_ci_attributes - ); + badges.insert(String::from("travis-ci"), test_badges.travis_ci_attributes); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); let current_badges = krate.badges(&conn).unwrap(); assert_eq!(current_badges.len(), 1); @@ -317,13 +253,10 @@ fn update_attributes() { repository: String::from("rust-lang/rust"), }; let mut badge_attributes_travis_ci2 = HashMap::new(); - badge_attributes_travis_ci2.insert( - String::from("repository"), - String::from("rust-lang/rust") - ); + badge_attributes_travis_ci2.insert(String::from("repository"), String::from("rust-lang/rust")); badges.insert( String::from("travis-ci"), - badge_attributes_travis_ci2.clone() + badge_attributes_travis_ci2.clone(), ); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); let current_badges = krate.badges(&conn).unwrap(); @@ -340,18 +273,9 @@ fn clear_badges() { let mut badges = HashMap::new(); // Adding 3 badges - badges.insert( - String::from("appveyor"), - test_badges.appveyor_attributes - ); - badges.insert( - String::from("travis-ci"), - test_badges.travis_ci_attributes - ); - badges.insert( - String::from("gitlab"), - test_badges.gitlab_attributes - ); + badges.insert(String::from("appveyor"), test_badges.appveyor_attributes); + badges.insert(String::from("travis-ci"), test_badges.travis_ci_attributes); + badges.insert(String::from("gitlab"), test_badges.gitlab_attributes); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); let current_badges = krate.badges(&conn).unwrap(); @@ -376,14 +300,8 @@ fn appveyor_extra_keys() { // Extra invalid keys are fine, they just get ignored let mut appveyor_attributes = test_badges.appveyor_attributes.clone(); - appveyor_attributes.insert( - String::from("extra"), - String::from("info") - ); - badges.insert( - String::from("appveyor"), - test_badges.appveyor_attributes - ); + appveyor_attributes.insert(String::from("extra"), String::from("info")); + badges.insert(String::from("appveyor"), test_badges.appveyor_attributes); Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(krate.badges(&conn).unwrap(), vec![test_badges.appveyor]); @@ -399,10 +317,7 @@ fn travis_ci_required_keys() { // Repository is a required key test_badges.travis_ci_attributes.remove("repository"); - badges.insert( - String::from("travis-ci"), - test_badges.travis_ci_attributes - ); + badges.insert(String::from("travis-ci"), test_badges.travis_ci_attributes); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); @@ -420,10 +335,7 @@ fn gitlab_required_keys() { // Repository is a required key test_badges.gitlab_attributes.remove("repository"); - badges.insert( - String::from("gitlab"), - test_badges.gitlab_attributes - ); + badges.insert(String::from("gitlab"), test_badges.gitlab_attributes); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); @@ -440,10 +352,12 @@ fn isitmaintained_issue_resolution_required_keys() { let mut badges = HashMap::new(); // Repository is a required key - test_badges.isitmaintained_issue_resolution_attributes.remove("repository"); + test_badges + .isitmaintained_issue_resolution_attributes + .remove("repository"); badges.insert( String::from("isitmaintained_issue_resolution"), - test_badges.isitmaintained_issue_resolution_attributes + test_badges.isitmaintained_issue_resolution_attributes, ); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); @@ -461,10 +375,12 @@ fn isitmaintained_open_issues_required_keys() { let mut badges = HashMap::new(); // Repository is a required key - test_badges.isitmaintained_open_issues_attributes.remove("repository"); + test_badges + .isitmaintained_open_issues_attributes + .remove("repository"); badges.insert( String::from("isitmaintained_open_issues"), - test_badges.isitmaintained_open_issues_attributes + test_badges.isitmaintained_open_issues_attributes, ); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); @@ -483,10 +399,7 @@ fn codecov_required_keys() { // Repository is a required key test_badges.codecov_attributes.remove("repository"); - badges.insert( - String::from("codecov"), - test_badges.codecov_attributes - ); + badges.insert(String::from("codecov"), test_badges.codecov_attributes); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); @@ -504,10 +417,7 @@ fn coveralls_required_keys() { // Repository is a required key test_badges.coveralls_attributes.remove("repository"); - badges.insert( - String::from("coveralls"), - test_badges.coveralls_attributes - ); + badges.insert(String::from("coveralls"), test_badges.coveralls_attributes); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); @@ -527,12 +437,9 @@ fn unknown_badge() { let mut invalid_attributes = HashMap::new(); invalid_attributes.insert( String::from("not-a-badge-attribute"), - String::from("not-a-badge-value") - ); - badges.insert( - String::from("not-a-badge"), - invalid_attributes + String::from("not-a-badge-value"), ); + badges.insert(String::from("not-a-badge"), invalid_attributes); let invalid_badges = Badge::update_crate(&conn, &krate, Some(&badges)).unwrap(); assert_eq!(invalid_badges.len(), 1); diff --git a/src/tests/category.rs b/src/tests/category.rs index b1beb4a1f3b..b251448a3eb 100644 --- a/src/tests/category.rs +++ b/src/tests/category.rs @@ -5,14 +5,21 @@ use cargo_registry::db::RequestTransaction; use cargo_registry::category::{Category, EncodableCategory, EncodableCategoryWithSubcategories}; #[derive(RustcDecodable)] -struct CategoryList { categories: Vec, meta: CategoryMeta } +struct CategoryList { + categories: Vec, + meta: CategoryMeta, +} #[derive(RustcDecodable)] -struct CategoryMeta { total: i32 } +struct CategoryMeta { + total: i32, +} #[derive(RustcDecodable)] -struct GoodCategory { category: EncodableCategory } +struct GoodCategory { + category: EncodableCategory, +} #[derive(RustcDecodable)] struct CategoryWithSubcategories { - category: EncodableCategoryWithSubcategories + category: EncodableCategoryWithSubcategories, } #[test] @@ -86,9 +93,7 @@ fn update_crate() { assert_eq!(cnt(&mut req, "category-2"), 0); // Replacing one category with another - Category::update_crate_old( - req.tx().unwrap(), &krate, &["category-2".to_string()] - ).unwrap(); + Category::update_crate_old(req.tx().unwrap(), &krate, &["category-2".to_string()]).unwrap(); assert_eq!(cnt(&mut req, "cat1"), 0); assert_eq!(cnt(&mut req, "category-2"), 1); @@ -99,8 +104,11 @@ fn update_crate() { // Adding 2 categories Category::update_crate_old( - req.tx().unwrap(), &krate, &["cat1".to_string(), - "category-2".to_string()]).unwrap(); + req.tx().unwrap(), + &krate, + &["cat1".to_string(), "category-2".to_string()], + ) + .unwrap(); assert_eq!(cnt(&mut req, "cat1"), 1); assert_eq!(cnt(&mut req, "category-2"), 1); @@ -111,9 +119,11 @@ fn update_crate() { // Attempting to add one valid category and one invalid category let invalid_categories = Category::update_crate_old( - req.tx().unwrap(), &krate, &["cat1".to_string(), - "catnope".to_string()] - ).unwrap(); + req.tx().unwrap(), + &krate, + &["cat1".to_string(), "catnope".to_string()], + ) + .unwrap(); assert_eq!(invalid_categories, vec!["catnope".to_string()]); assert_eq!(cnt(&mut req, "cat1"), 1); assert_eq!(cnt(&mut req, "category-2"), 0); @@ -127,17 +137,18 @@ fn update_crate() { assert_eq!(json.meta.total, 2); // Attempting to add a category by display text; must use slug - Category::update_crate_old( - req.tx().unwrap(), &krate, &["Category 2".to_string()] - ).unwrap(); + Category::update_crate_old(req.tx().unwrap(), &krate, &["Category 2".to_string()]).unwrap(); assert_eq!(cnt(&mut req, "cat1"), 0); assert_eq!(cnt(&mut req, "category-2"), 0); // Add a category and its subcategory ::mock_category(&mut req, "cat1::bar", "cat1::bar"); Category::update_crate_old( - req.tx().unwrap(), &krate, &["cat1".to_string(), - "cat1::bar".to_string()]).unwrap(); + req.tx().unwrap(), + &krate, + &["cat1".to_string(), "cat1::bar".to_string()], + ) + .unwrap(); assert_eq!(cnt(&mut req, "cat1"), 1); assert_eq!(cnt(&mut req, "cat1::bar"), 1); assert_eq!(cnt(&mut req, "category-2"), 0); diff --git a/src/tests/git.rs b/src/tests/git.rs index feac51e3177..bd2309fd66d 100644 --- a/src/tests/git.rs +++ b/src/tests/git.rs @@ -8,20 +8,25 @@ use git2; use url::Url; fn root() -> PathBuf { - env::current_dir().unwrap().join("tmp").join(thread::current().name().unwrap()) + env::current_dir() + .unwrap() + .join("tmp") + .join(thread::current().name().unwrap()) } -pub fn checkout() -> PathBuf { root().join("checkout") } -pub fn bare() -> PathBuf { root().join("bare") } +pub fn checkout() -> PathBuf { + root().join("checkout") +} +pub fn bare() -> PathBuf { + root().join("bare") +} pub fn init() { static INIT: Once = ONCE_INIT; let _ = fs::remove_dir_all(&checkout()); let _ = fs::remove_dir_all(&bare()); - INIT.call_once(|| { - fs::create_dir_all(root().parent().unwrap()).unwrap(); - }); + INIT.call_once(|| { fs::create_dir_all(root().parent().unwrap()).unwrap(); }); // Prepare a bare remote repo { @@ -38,7 +43,9 @@ pub fn init() { // Setup the `origin` remote checkout.remote_set_url("origin", &url).unwrap(); checkout.remote_set_pushurl("origin", Some(&url)).unwrap(); - checkout.remote_add_push("origin", "refs/heads/master").unwrap(); + checkout + .remote_add_push("origin", "refs/heads/master") + .unwrap(); // Create an empty initial commit let mut config = checkout.config().unwrap(); @@ -48,9 +55,9 @@ pub fn init() { let id = index.write_tree().unwrap(); let tree = checkout.find_tree(id).unwrap(); let sig = checkout.signature().unwrap(); - checkout.commit(Some("HEAD"), &sig, &sig, - "Initial Commit", - &tree, &[]).unwrap(); + checkout + .commit(Some("HEAD"), &sig, &sig, "Initial Commit", &tree, &[]) + .unwrap(); // Push the commit to the remote repo let mut origin = checkout.find_remote("origin").unwrap(); diff --git a/src/tests/keyword.rs b/src/tests/keyword.rs index 8d78f89f049..980615800d9 100644 --- a/src/tests/keyword.rs +++ b/src/tests/keyword.rs @@ -4,11 +4,18 @@ use conduit_test::MockRequest; use cargo_registry::keyword::{Keyword, EncodableKeyword}; #[derive(RustcDecodable)] -struct KeywordList { keywords: Vec, meta: KeywordMeta } +struct KeywordList { + keywords: Vec, + meta: KeywordMeta, +} #[derive(RustcDecodable)] -struct KeywordMeta { total: i32 } +struct KeywordMeta { + total: i32, +} #[derive(RustcDecodable)] -struct GoodKeyword { keyword: EncodableKeyword } +struct GoodKeyword { + keyword: EncodableKeyword, +} #[test] fn index() { @@ -72,12 +79,9 @@ fn update_crate() { let krate = { let conn = app.diesel_database.get().unwrap(); - let u = ::new_user("foo") - .create_or_update(&conn) - .unwrap(); + let u = ::new_user("foo").create_or_update(&conn).unwrap(); Keyword::find_or_create_all(&conn, &["kw1", "kw2"]).unwrap(); - ::CrateBuilder::new("fookey", u.id) - .expect_build(&conn) + ::CrateBuilder::new("fookey", u.id).expect_build(&conn) }; { diff --git a/src/tests/krate.rs b/src/tests/krate.rs index 98f2838bd2f..ceb2aa27cff 100644 --- a/src/tests/krate.rs +++ b/src/tests/krate.rs @@ -20,23 +20,47 @@ use cargo_registry::version::EncodableVersion; use cargo_registry::category::Category; #[derive(RustcDecodable)] -struct CrateList { crates: Vec, meta: CrateMeta } +struct CrateList { + crates: Vec, + meta: CrateMeta, +} #[derive(RustcDecodable)] -struct VersionsList { versions: Vec } +struct VersionsList { + versions: Vec, +} #[derive(RustcDecodable)] -struct CrateMeta { total: i32 } +struct CrateMeta { + total: i32, +} #[derive(RustcDecodable)] -struct Warnings { invalid_categories: Vec, invalid_badges: Vec } +struct Warnings { + invalid_categories: Vec, + invalid_badges: Vec, +} #[derive(RustcDecodable)] -struct GoodCrate { krate: EncodableCrate, warnings: Warnings } +struct GoodCrate { + krate: EncodableCrate, + warnings: Warnings, +} #[derive(RustcDecodable)] -struct CrateResponse { krate: EncodableCrate, versions: Vec, keywords: Vec } +struct CrateResponse { + krate: EncodableCrate, + versions: Vec, + keywords: Vec, +} #[derive(RustcDecodable)] -struct Deps { dependencies: Vec } +struct Deps { + dependencies: Vec, +} #[derive(RustcDecodable)] -struct RevDeps { dependencies: Vec, meta: CrateMeta } +struct RevDeps { + dependencies: Vec, + meta: CrateMeta, +} #[derive(RustcDecodable)] -struct Downloads { version_downloads: Vec } +struct Downloads { + version_downloads: Vec, +} fn new_crate(name: &str) -> u::NewCrate { u::NewCrate { @@ -69,11 +93,8 @@ fn index() { let krate = { let conn = app.diesel_database.get().unwrap(); - let u = ::new_user("foo") - .create_or_update(&conn) - .unwrap(); - ::CrateBuilder::new("fooindex", u.id) - .expect_build(&conn) + let u = ::new_user("foo").create_or_update(&conn).unwrap(); + ::CrateBuilder::new("fooindex", u.id).expect_build(&conn) }; let mut response = ok_resp!(middle.call(&mut req)); @@ -93,9 +114,7 @@ fn index_queries() { let krate2; { let conn = app.diesel_database.get().unwrap(); - u = ::new_user("foo") - .create_or_update(&conn) - .unwrap(); + u = ::new_user("foo").create_or_update(&conn).unwrap(); krate = ::CrateBuilder::new("foo_index_queries", u.id) .readme("readme") @@ -155,8 +174,12 @@ fn index_queries() { { let conn = app.diesel_database.get().unwrap(); - ::new_category("Category 1", "cat1").find_or_create(&conn).unwrap(); - ::new_category("Category 1::Ba'r", "cat1::bar").find_or_create(&conn).unwrap(); + ::new_category("Category 1", "cat1") + .find_or_create(&conn) + .unwrap(); + ::new_category("Category 1::Ba'r", "cat1::bar") + .find_or_create(&conn) + .unwrap(); Category::update_crate(&conn, &krate, &["cat1"]).unwrap(); Category::update_crate(&conn, &krate2, &["cat1::bar"]).unwrap(); } @@ -334,8 +357,11 @@ fn show() { assert_eq!(json.versions[0].krate, json.krate.id); assert_eq!(json.versions[0].num, "1.0.0"); let suffix = "/api/v1/crates/foo_show/1.0.0/download"; - assert!(json.versions[0].dl_path.ends_with(suffix), - "bad suffix {}", json.versions[0].dl_path); + assert!( + json.versions[0].dl_path.ends_with(suffix), + "bad suffix {}", + json.versions[0].dl_path + ); assert_eq!(1, json.keywords.len()); assert_eq!("kw1", json.keywords[0].id); @@ -394,8 +420,11 @@ fn new_bad_names() { let mut req = ::new_req(app, name, "1.0.0"); ::mock_user(&mut req, ::user("foo")); let json = bad_resp!(middle.call(&mut req)); - assert!(json.errors[0].detail.contains("invalid crate name"), - "{:?}", json.errors); + assert!( + json.errors[0].detail.contains("invalid crate name"), + "{:?}", + json.errors + ); } bad_name(""); @@ -421,7 +450,11 @@ fn new_krate_with_reserved_name() { let mut req = ::new_req(app, name, "1.0.0"); ::mock_user(&mut req, ::user("foo")); let json = bad_resp!(middle.call(&mut req)); - assert!(json.errors[0].detail.contains("cannot upload a crate with a reserved name")); + assert!( + json.errors[0] + .detail + .contains("cannot upload a crate with a reserved name") + ); } test_bad_name("std"); @@ -468,7 +501,10 @@ fn new_krate_with_dependency() { let path = ::git::checkout().join("ne/w_/new_dep"); assert!(path.exists()); let mut contents = String::new(); - File::open(&path).unwrap().read_to_string(&mut contents).unwrap(); + File::open(&path) + .unwrap() + .read_to_string(&mut contents) + .unwrap(); let p: git::Crate = json::decode(&contents).unwrap(); assert_eq!(p.name, "new_dep"); assert_eq!(p.vers, "1.0.0"); @@ -523,7 +559,11 @@ fn new_krate_with_wildcard_dependency() { ::CrateBuilder::new("foo_wild", user.id).expect_build(&conn); } let json = bad_resp!(middle.call(&mut req)); - assert!(json.errors[0].detail.contains("dependency constraints"), "{:?}", json.errors); + assert!( + json.errors[0].detail.contains("dependency constraints"), + "{:?}", + json.errors + ); } #[test] @@ -562,8 +602,11 @@ fn new_krate_wrong_user() { } let json = bad_resp!(middle.call(&mut req)); - assert!(json.errors[0].detail.contains("another user"), - "{:?}", json.errors); + assert!( + json.errors[0].detail.contains("another user"), + "{:?}", + json.errors + ); } #[test] @@ -574,21 +617,30 @@ fn new_krate_bad_name() { let mut req = ::new_req(app.clone(), "snow☃", "2.0.0"); ::sign_in(&mut req, &app); let json = bad_resp!(middle.call(&mut req)); - assert!(json.errors[0].detail.contains("invalid crate name"), - "{:?}", json.errors); + assert!( + json.errors[0].detail.contains("invalid crate name"), + "{:?}", + json.errors + ); } { let mut req = ::new_req(app.clone(), "áccênts", "2.0.0"); ::sign_in(&mut req, &app); let json = bad_resp!(middle.call(&mut req)); - assert!(json.errors[0].detail.contains("invalid crate name"), - "{:?}", json.errors); + assert!( + json.errors[0].detail.contains("invalid crate name"), + "{:?}", + json.errors + ); } } #[test] fn new_crate_owner() { - #[derive(RustcDecodable)] struct O { ok: bool } + #[derive(RustcDecodable)] + struct O { + ok: bool, + } let (_b, app, middle) = ::app(); @@ -605,27 +657,43 @@ fn new_crate_owner() { // Flag the second user as an owner let body = r#"{"users":["bar"]}"#; - let mut response = ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_owner/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + let mut response = ok_resp!( + middle.call( + req.with_path("/api/v1/crates/foo_owner/owners") + .with_method(Method::Put) + .with_body(body.as_bytes()) + ) + ); assert!(::json::(&mut response).ok); - bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_owner/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + bad_resp!( + middle.call( + req.with_path("/api/v1/crates/foo_owner/owners") + .with_method(Method::Put) + .with_body(body.as_bytes()) + ) + ); // Make sure this shows up as one of their crates. let query = format!("user_id={}", u2.id); - let mut response = ok_resp!(middle.call(req.with_path("/api/v1/crates") - .with_method(Method::Get) - .with_query(&query))); + let mut response = ok_resp!( + middle.call( + req.with_path("/api/v1/crates") + .with_method(Method::Get) + .with_query(&query) + ) + ); assert_eq!(::json::(&mut response).crates.len(), 1); // And upload a new crate as the first user let body = ::new_req_body_version_2(::krate("foo_owner")); ::sign_in_as(&mut req, &u2); - let mut response = ok_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_method(Method::Put) - .with_body(&body))); + let mut response = ok_resp!( + middle.call( + req.with_path("/api/v1/crates/new") + .with_method(Method::Put) + .with_body(&body) + ) + ); ::json::(&mut response); } @@ -678,8 +746,11 @@ fn new_krate_duplicate_version() { .expect_build(&conn); } let json = bad_resp!(middle.call(&mut req)); - assert!(json.errors[0].detail.contains("already uploaded"), - "{:?}", json.errors); + assert!( + json.errors[0].detail.contains("already uploaded"), + "{:?}", + json.errors + ); } #[test] @@ -693,8 +764,11 @@ fn new_crate_similar_name() { ::CrateBuilder::new("Foo_similar", u.id).expect_build(&conn); } let json = bad_resp!(middle.call(&mut req)); - assert!(json.errors[0].detail.contains("previously named"), - "{:?}", json.errors); + assert!( + json.errors[0].detail.contains("previously named"), + "{:?}", + json.errors + ); } #[test] @@ -708,8 +782,11 @@ fn new_crate_similar_name_hyphen() { ::CrateBuilder::new("foo_bar_hyphen", u.id).expect_build(&conn); } let json = bad_resp!(middle.call(&mut req)); - assert!(json.errors[0].detail.contains("previously named"), - "{:?}", json.errors); + assert!( + json.errors[0].detail.contains("previously named"), + "{:?}", + json.errors + ); } #[test] @@ -723,8 +800,11 @@ fn new_crate_similar_name_underscore() { ::CrateBuilder::new("foo-bar-underscore", u.id).expect_build(&conn); } let json = bad_resp!(middle.call(&mut req)); - assert!(json.errors[0].detail.contains("previously named"), - "{:?}", json.errors); + assert!( + json.errors[0].detail.contains("previously named"), + "{:?}", + json.errors + ); } #[test] @@ -738,13 +818,18 @@ fn new_krate_git_upload() { let path = ::git::checkout().join("3/f/fgt"); assert!(path.exists()); let mut contents = String::new(); - File::open(&path).unwrap().read_to_string(&mut contents).unwrap(); + File::open(&path) + .unwrap() + .read_to_string(&mut contents) + .unwrap(); let p: git::Crate = json::decode(&contents).unwrap(); assert_eq!(p.name, "fgt"); assert_eq!(p.vers, "1.0.0"); assert!(p.deps.is_empty()); - assert_eq!(p.cksum, - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); + assert_eq!( + p.cksum, + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + ); } #[test] @@ -752,9 +837,13 @@ fn new_krate_git_upload_appends() { let (_b, app, middle) = ::app(); let path = ::git::checkout().join("3/f/fpp"); fs::create_dir_all(path.parent().unwrap()).unwrap(); - File::create(&path).unwrap().write_all( - br#"{"name":"FPP","vers":"0.0.1","deps":[],"features":{},"cksum":"3j3"} -"#).unwrap(); + File::create(&path) + .unwrap() + .write_all( + br#"{"name":"FPP","vers":"0.0.1","deps":[],"features":{},"cksum":"3j3"} +"# + ) + .unwrap(); let mut req = ::new_req(app.clone(), "FPP", "1.0.0"); ::sign_in(&mut req, &app); @@ -762,7 +851,10 @@ fn new_krate_git_upload_appends() { ::json::(&mut response); let mut contents = String::new(); - File::open(&path).unwrap().read_to_string(&mut contents).unwrap(); + File::open(&path) + .unwrap() + .read_to_string(&mut contents) + .unwrap(); let mut lines = contents.lines(); let p1: git::Crate = json::decode(lines.next().unwrap().trim()).unwrap(); let p2: git::Crate = json::decode(lines.next().unwrap().trim()).unwrap(); @@ -785,8 +877,8 @@ fn new_krate_git_upload_with_conflicts() { let sig = repo.signature().unwrap(); let parent = repo.find_commit(target).unwrap(); let tree = repo.find_tree(parent.tree_id()).unwrap(); - repo.commit(Some("HEAD"), &sig, &sig, "empty commit", &tree, - &[&parent]).unwrap(); + repo.commit(Some("HEAD"), &sig, &sig, "empty commit", &tree, &[&parent]) + .unwrap(); } let mut req = ::new_req(app.clone(), "foo_conflicts", "1.0.0"); @@ -811,8 +903,11 @@ fn new_krate_dependency_missing() { ::sign_in(&mut req, &app); let mut response = ok_resp!(middle.call(&mut req)); let json = ::json::<::Bad>(&mut response); - assert!(json.errors[0].detail - .contains("no known crate named `bar_missing`")); + assert!( + json.errors[0] + .detail + .contains("no known crate named `bar_missing`") + ); } #[test] @@ -824,9 +919,13 @@ fn summary_doesnt_die() { #[test] fn download() { - use ::time::{Duration, now_utc, strftime}; + use time::{Duration, now_utc, strftime}; let (_b, app, middle) = ::app(); - let mut req = ::req(app.clone(), Method::Get, "/api/v1/crates/foo_download/1.0.0/download"); + let mut req = ::req( + app.clone(), + Method::Get, + "/api/v1/crates/foo_download/1.0.0/download", + ); { let conn = app.diesel_database.get().unwrap(); let user = ::new_user("foo").create_or_update(&conn).unwrap(); @@ -888,12 +987,15 @@ fn download() { #[test] fn download_bad() { let (_b, app, middle) = ::app(); - let mut req = ::req(app.clone(), Method::Get, "/api/v1/crates/foo_bad/0.1.0/download"); + let mut req = ::req( + app.clone(), + Method::Get, + "/api/v1/crates/foo_bad/0.1.0/download", + ); { let conn = app.diesel_database.get().unwrap(); let user = ::new_user("foo").create_or_update(&conn).unwrap(); - ::CrateBuilder::new("foo_bad", user.id) - .expect_build(&conn); + ::CrateBuilder::new("foo_bad", user.id).expect_build(&conn); } let response = t_resp!(middle.call(&mut req)); assert_eq!(404, response.status.0) @@ -903,15 +1005,17 @@ fn download_bad() { fn dependencies() { let (_b, app, middle) = ::app(); - let mut req = ::req(app.clone(), Method::Get, "/api/v1/crates/foo_deps/1.0.0/dependencies"); + let mut req = ::req( + app.clone(), + Method::Get, + "/api/v1/crates/foo_deps/1.0.0/dependencies", + ); { let conn = app.diesel_database.get().unwrap(); let user = ::new_user("foo").create_or_update(&conn).unwrap(); - let c1 = ::CrateBuilder::new("foo_deps", user.id) - .expect_build(&conn); + let c1 = ::CrateBuilder::new("foo_deps", user.id).expect_build(&conn); let v = ::new_version(c1.id, "1.0.0").save(&conn, &[]).unwrap(); - let c2 = ::CrateBuilder::new("bar_deps", user.id) - .expect_build(&conn); + let c2 = ::CrateBuilder::new("bar_deps", user.id).expect_build(&conn); ::new_dependency(&conn, &v, &c2); } @@ -927,7 +1031,11 @@ fn dependencies() { #[test] fn diesel_not_found_results_in_404() { let (_b, app, middle) = ::app(); - let mut req = ::req(app.clone(), Method::Get, "/api/v1/crates/foo_following/following"); + let mut req = ::req( + app.clone(), + Method::Get, + "/api/v1/crates/foo_following/following", + ); { let conn = app.diesel_database.get().unwrap(); @@ -941,11 +1049,21 @@ fn diesel_not_found_results_in_404() { #[test] fn following() { - #[derive(RustcDecodable)] struct F { following: bool } - #[derive(RustcDecodable)] struct O { ok: bool } + #[derive(RustcDecodable)] + struct F { + following: bool, + } + #[derive(RustcDecodable)] + struct O { + ok: bool, + } let (_b, app, middle) = ::app(); - let mut req = ::req(app.clone(), Method::Get, "/api/v1/crates/foo_following/following"); + let mut req = ::req( + app.clone(), + Method::Get, + "/api/v1/crates/foo_following/following", + ); let user; { @@ -959,14 +1077,14 @@ fn following() { assert!(!::json::(&mut response).following); req.with_path("/api/v1/crates/foo_following/follow") - .with_method(Method::Put); + .with_method(Method::Put); let mut response = ok_resp!(middle.call(&mut req)); assert!(::json::(&mut response).ok); let mut response = ok_resp!(middle.call(&mut req)); assert!(::json::(&mut response).ok); req.with_path("/api/v1/crates/foo_following/following") - .with_method(Method::Get); + .with_method(Method::Get); let mut response = ok_resp!(middle.call(&mut req)); assert!(::json::(&mut response).following); @@ -978,28 +1096,34 @@ fn following() { assert_eq!(l.crates.len(), 1); req.with_path("/api/v1/crates/foo_following/follow") - .with_method(Method::Delete); + .with_method(Method::Delete); let mut response = ok_resp!(middle.call(&mut req)); assert!(::json::(&mut response).ok); let mut response = ok_resp!(middle.call(&mut req)); assert!(::json::(&mut response).ok); req.with_path("/api/v1/crates/foo_following/following") - .with_method(Method::Get); + .with_method(Method::Get); let mut response = ok_resp!(middle.call(&mut req)); assert!(!::json::(&mut response).following); req.with_path("/api/v1/crates") - .with_query("following=1") - .with_method(Method::Get); + .with_query("following=1") + .with_method(Method::Get); let mut response = ok_resp!(middle.call(&mut req)); assert_eq!(::json::(&mut response).crates.len(), 0); } #[test] fn owners() { - #[derive(RustcDecodable)] struct R { users: Vec } - #[derive(RustcDecodable)] struct O { ok: bool } + #[derive(RustcDecodable)] + struct R { + users: Vec, + } + #[derive(RustcDecodable)] + struct O { + ok: bool, + } let (_b, app, middle) = ::app(); let mut req = ::req(app.clone(), Method::Get, "/api/v1/crates/foo_owners/owners"); @@ -1020,8 +1144,7 @@ fn owners() { assert_eq!(r.users.len(), 1); let body = r#"{"users":["foobar"]}"#; - let mut response = ok_resp!(middle.call(req.with_method(Method::Put) - .with_body(body.as_bytes()))); + let mut response = ok_resp!(middle.call(req.with_method(Method::Put).with_body(body.as_bytes()))); assert!(::json::(&mut response).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get))); @@ -1029,8 +1152,7 @@ fn owners() { assert_eq!(r.users.len(), 2); let body = r#"{"users":["foobar"]}"#; - let mut response = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_body(body.as_bytes()))); + let mut response = ok_resp!(middle.call(req.with_method(Method::Delete).with_body(body.as_bytes()))); assert!(::json::(&mut response).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get))); @@ -1038,20 +1160,24 @@ fn owners() { assert_eq!(r.users.len(), 1); let body = r#"{"users":["foo"]}"#; - let mut response = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_body(body.as_bytes()))); + let mut response = ok_resp!(middle.call(req.with_method(Method::Delete).with_body(body.as_bytes()))); ::json::<::Bad>(&mut response); let body = r#"{"users":["foobar"]}"#; - let mut response = ok_resp!(middle.call(req.with_method(Method::Put) - .with_body(body.as_bytes()))); + let mut response = ok_resp!(middle.call(req.with_method(Method::Put).with_body(body.as_bytes()))); assert!(::json::(&mut response).ok); } #[test] fn yank() { - #[derive(RustcDecodable)] struct O { ok: bool } - #[derive(RustcDecodable)] struct V { version: EncodableVersion } + #[derive(RustcDecodable)] + struct O { + ok: bool, + } + #[derive(RustcDecodable)] + struct V { + version: EncodableVersion, + } let (_b, app, middle) = ::app(); let path = ::git::checkout().join("3/f/fyk"); @@ -1061,44 +1187,73 @@ fn yank() { let mut response = ok_resp!(middle.call(&mut req)); ::json::(&mut response); let mut contents = String::new(); - File::open(&path).unwrap().read_to_string(&mut contents).unwrap(); + File::open(&path) + .unwrap() + .read_to_string(&mut contents) + .unwrap(); assert!(contents.contains("\"yanked\":false")); // make sure it's not yanked - let mut r = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk/1.0.0"))); + let mut r = ok_resp!( + middle.call( + req.with_method(Method::Get) + .with_path("/api/v1/crates/fyk/1.0.0") + ) + ); assert!(!::json::(&mut r).version.yanked); // yank it - let mut r = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_path("/api/v1/crates/fyk/1.0.0/yank"))); + let mut r = ok_resp!( + middle.call( + req.with_method(Method::Delete) + .with_path("/api/v1/crates/fyk/1.0.0/yank") + ) + ); assert!(::json::(&mut r).ok); let mut contents = String::new(); - File::open(&path).unwrap().read_to_string(&mut contents).unwrap(); + File::open(&path) + .unwrap() + .read_to_string(&mut contents) + .unwrap(); assert!(contents.contains("\"yanked\":true")); - let mut r = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk/1.0.0"))); + let mut r = ok_resp!( + middle.call( + req.with_method(Method::Get) + .with_path("/api/v1/crates/fyk/1.0.0") + ) + ); assert!(::json::(&mut r).version.yanked); // un-yank it - let mut r = ok_resp!(middle.call(req.with_method(Method::Put) - .with_path("/api/v1/crates/fyk/1.0.0/unyank"))); + let mut r = ok_resp!( + middle.call( + req.with_method(Method::Put) + .with_path("/api/v1/crates/fyk/1.0.0/unyank") + ) + ); assert!(::json::(&mut r).ok); let mut contents = String::new(); - File::open(&path).unwrap().read_to_string(&mut contents).unwrap(); + File::open(&path) + .unwrap() + .read_to_string(&mut contents) + .unwrap(); assert!(contents.contains("\"yanked\":false")); - let mut r = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk/1.0.0"))); + let mut r = ok_resp!( + middle.call( + req.with_method(Method::Get) + .with_path("/api/v1/crates/fyk/1.0.0") + ) + ); assert!(!::json::(&mut r).version.yanked); } #[test] fn yank_not_owner() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, ::new_user("bar"), "foo_not"); + let mut req = ::request_with_user_and_mock_crate(&app, ::new_user("bar"), "foo_not"); ::sign_in(&mut req, &app); - req.with_method(Method::Delete).with_path("/api/v1/crates/foo_not/1.0.0/yank"); + req.with_method(Method::Delete) + .with_path("/api/v1/crates/foo_not/1.0.0/yank"); let mut response = ok_resp!(middle.call(&mut req)); ::json::<::Bad>(&mut response); } @@ -1122,63 +1277,115 @@ fn yank_max_version() { // add version 2.0.0 let body = ::new_req_body_version_2(::krate("fyk_max")); - let mut response = ok_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_method(Method::Put) - .with_body(&body))); + let mut response = ok_resp!( + middle.call( + req.with_path("/api/v1/crates/new") + .with_method(Method::Put) + .with_body(&body) + ) + ); let json: GoodCrate = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); // yank version 1.0.0 - let mut r = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_path("/api/v1/crates/fyk_max/1.0.0/yank"))); + let mut r = ok_resp!( + middle.call( + req.with_method(Method::Delete) + .with_path("/api/v1/crates/fyk_max/1.0.0/yank") + ) + ); assert!(::json::(&mut r).ok); - let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + let mut response = ok_resp!( + middle.call( + req.with_method(Method::Get) + .with_path("/api/v1/crates/fyk_max") + ) + ); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); // unyank version 1.0.0 - let mut r = ok_resp!(middle.call(req.with_method(Method::Put) - .with_path("/api/v1/crates/fyk_max/1.0.0/unyank"))); + let mut r = ok_resp!( + middle.call( + req.with_method(Method::Put) + .with_path("/api/v1/crates/fyk_max/1.0.0/unyank") + ) + ); assert!(::json::(&mut r).ok); - let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + let mut response = ok_resp!( + middle.call( + req.with_method(Method::Get) + .with_path("/api/v1/crates/fyk_max") + ) + ); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); // yank version 2.0.0 - let mut r = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_path("/api/v1/crates/fyk_max/2.0.0/yank"))); + let mut r = ok_resp!( + middle.call( + req.with_method(Method::Delete) + .with_path("/api/v1/crates/fyk_max/2.0.0/yank") + ) + ); assert!(::json::(&mut r).ok); - let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + let mut response = ok_resp!( + middle.call( + req.with_method(Method::Get) + .with_path("/api/v1/crates/fyk_max") + ) + ); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "1.0.0"); // yank version 1.0.0 - let mut r = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_path("/api/v1/crates/fyk_max/1.0.0/yank"))); + let mut r = ok_resp!( + middle.call( + req.with_method(Method::Delete) + .with_path("/api/v1/crates/fyk_max/1.0.0/yank") + ) + ); assert!(::json::(&mut r).ok); - let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + let mut response = ok_resp!( + middle.call( + req.with_method(Method::Get) + .with_path("/api/v1/crates/fyk_max") + ) + ); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "0.0.0"); // unyank version 2.0.0 - let mut r = ok_resp!(middle.call(req.with_method(Method::Put) - .with_path("/api/v1/crates/fyk_max/2.0.0/unyank"))); + let mut r = ok_resp!( + middle.call( + req.with_method(Method::Put) + .with_path("/api/v1/crates/fyk_max/2.0.0/unyank") + ) + ); assert!(::json::(&mut r).ok); - let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + let mut response = ok_resp!( + middle.call( + req.with_method(Method::Get) + .with_path("/api/v1/crates/fyk_max") + ) + ); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); // unyank version 1.0.0 - let mut r = ok_resp!(middle.call(req.with_method(Method::Put) - .with_path("/api/v1/crates/fyk_max/1.0.0/unyank"))); + let mut r = ok_resp!( + middle.call( + req.with_method(Method::Put) + .with_path("/api/v1/crates/fyk_max/1.0.0/unyank") + ) + ); assert!(::json::(&mut r).ok); - let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + let mut response = ok_resp!( + middle.call( + req.with_method(Method::Get) + .with_path("/api/v1/crates/fyk_max") + ) + ); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); } @@ -1201,28 +1408,48 @@ fn publish_after_yank_max_version() { assert_eq!(json.krate.max_version, "1.0.0"); // yank version 1.0.0 - let mut r = ok_resp!(middle.call(req.with_method(Method::Delete) - .with_path("/api/v1/crates/fyk_max/1.0.0/yank"))); + let mut r = ok_resp!( + middle.call( + req.with_method(Method::Delete) + .with_path("/api/v1/crates/fyk_max/1.0.0/yank") + ) + ); assert!(::json::(&mut r).ok); - let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + let mut response = ok_resp!( + middle.call( + req.with_method(Method::Get) + .with_path("/api/v1/crates/fyk_max") + ) + ); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "0.0.0"); // add version 2.0.0 let body = ::new_req_body_version_2(::krate("fyk_max")); - let mut response = ok_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_method(Method::Put) - .with_body(&body))); + let mut response = ok_resp!( + middle.call( + req.with_path("/api/v1/crates/new") + .with_method(Method::Put) + .with_body(&body) + ) + ); let json: GoodCrate = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); // unyank version 1.0.0 - let mut r = ok_resp!(middle.call(req.with_method(Method::Put) - .with_path("/api/v1/crates/fyk_max/1.0.0/unyank"))); + let mut r = ok_resp!( + middle.call( + req.with_method(Method::Put) + .with_path("/api/v1/crates/fyk_max/1.0.0/unyank") + ) + ); assert!(::json::(&mut r).ok); - let mut response = ok_resp!(middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max"))); + let mut response = ok_resp!( + middle.call( + req.with_method(Method::Get) + .with_path("/api/v1/crates/fyk_max") + ) + ); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); } @@ -1273,7 +1500,9 @@ fn good_categories() { ::sign_in(&mut req, &app); { let conn = app.diesel_database.get().unwrap(); - ::new_category("Category 1", "cat1").find_or_create(&conn).unwrap(); + ::new_category("Category 1", "cat1") + .find_or_create(&conn) + .unwrap(); } let mut response = ok_resp!(middle.call(&mut req)); let json: GoodCrate = ::json(&mut response); @@ -1303,7 +1532,7 @@ fn good_badges() { let mut badge_attributes = HashMap::new(); badge_attributes.insert( String::from("repository"), - String::from("rust-lang/crates.io") + String::from("rust-lang/crates.io"), ); badges.insert(String::from("travis-ci"), badge_attributes); @@ -1317,8 +1546,11 @@ fn good_badges() { assert_eq!(json.krate.max_version, "1.0.0"); let mut response = ok_resp!( - middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/foobadger"))); + middle.call( + req.with_method(Method::Get) + .with_path("/api/v1/crates/foobadger") + ) + ); let json: CrateResponse = ::json(&mut response); @@ -1338,18 +1570,12 @@ fn ignored_badges() { // Known badge type, missing required repository attribute let mut badge_attributes = HashMap::new(); - badge_attributes.insert( - String::from("branch"), - String::from("master") - ); + badge_attributes.insert(String::from("branch"), String::from("master")); badges.insert(String::from("travis-ci"), badge_attributes); // Unknown badge type let mut unknown_badge_attributes = HashMap::new(); - unknown_badge_attributes.insert( - String::from("repository"), - String::from("rust-lang/rust") - ); + unknown_badge_attributes.insert(String::from("repository"), String::from("rust-lang/rust")); badges.insert(String::from("not-a-badge"), unknown_badge_attributes); let (_b, app, middle) = ::app(); @@ -1362,12 +1588,23 @@ fn ignored_badges() { assert_eq!(json.krate.name, "foo_ignored_badge"); assert_eq!(json.krate.max_version, "1.0.0"); assert_eq!(json.warnings.invalid_badges.len(), 2); - assert!(json.warnings.invalid_badges.contains(&"travis-ci".to_string())); - assert!(json.warnings.invalid_badges.contains(&"not-a-badge".to_string())); + assert!( + json.warnings + .invalid_badges + .contains(&"travis-ci".to_string()) + ); + assert!( + json.warnings + .invalid_badges + .contains(&"not-a-badge".to_string()) + ); let mut response = ok_resp!( - middle.call(req.with_method(Method::Get) - .with_path("/api/v1/crates/foo_ignored_badge"))); + middle.call( + req.with_method(Method::Get) + .with_path("/api/v1/crates/foo_ignored_badge") + ) + ); let json: CrateResponse = ::json(&mut response); @@ -1381,8 +1618,7 @@ fn reverse_dependencies() { let v100 = semver::Version::parse("1.0.0").unwrap(); let v110 = semver::Version::parse("1.1.0").unwrap(); - let mut req = ::req(app, Method::Get, - "/api/v1/crates/c1/reverse_dependencies"); + let mut req = ::req(app, Method::Get, "/api/v1/crates/c1/reverse_dependencies"); ::mock_user(&mut req, ::user("foo")); let (c1, _) = ::mock_crate_vers(&mut req, ::krate("c1"), &v100); let (_, c2v1) = ::mock_crate_vers(&mut req, ::krate("c2"), &v100); @@ -1413,8 +1649,7 @@ fn reverse_dependencies_when_old_version_doesnt_depend_but_new_does() { let v100 = semver::Version::parse("1.0.0").unwrap(); let v110 = semver::Version::parse("1.1.0").unwrap(); let v200 = semver::Version::parse("2.0.0").unwrap(); - let mut req = ::req(app, Method::Get, - "/api/v1/crates/c1/reverse_dependencies"); + let mut req = ::req(app, Method::Get, "/api/v1/crates/c1/reverse_dependencies"); ::mock_user(&mut req, ::user("foo")); let (c1, _) = ::mock_crate_vers(&mut req, ::krate("c1"), &v110); let _ = ::mock_crate_vers(&mut req, ::krate("c2"), &v100); @@ -1435,8 +1670,7 @@ fn reverse_dependencies_when_old_version_depended_but_new_doesnt() { let v100 = semver::Version::parse("1.0.0").unwrap(); let v200 = semver::Version::parse("2.0.0").unwrap(); - let mut req = ::req(app, Method::Get, - "/api/v1/crates/c1/reverse_dependencies"); + let mut req = ::req(app, Method::Get, "/api/v1/crates/c1/reverse_dependencies"); ::mock_user(&mut req, ::user("foo")); let (c1, _) = ::mock_crate_vers(&mut req, ::krate("c1"), &v100); let (_, c2v1) = ::mock_crate_vers(&mut req, ::krate("c2"), &v100); @@ -1456,8 +1690,7 @@ fn prerelease_versions_not_included_in_reverse_dependencies() { let v100 = semver::Version::parse("1.0.0").unwrap(); let v110_pre = semver::Version::parse("1.1.0-pre").unwrap(); - let mut req = ::req(app, Method::Get, - "/api/v1/crates/c1/reverse_dependencies"); + let mut req = ::req(app, Method::Get, "/api/v1/crates/c1/reverse_dependencies"); ::mock_user(&mut req, ::user("foo")); let (c1, _) = ::mock_crate_vers(&mut req, ::krate("c1"), &v100); let _ = ::mock_crate_vers(&mut req, ::krate("c2"), &v110_pre); @@ -1479,8 +1712,7 @@ fn yanked_versions_not_included_in_reverse_dependencies() { let v100 = semver::Version::parse("1.0.0").unwrap(); let v200 = semver::Version::parse("2.0.0").unwrap(); - let mut req = ::req(app, Method::Get, - "/api/v1/crates/c1/reverse_dependencies"); + let mut req = ::req(app, Method::Get, "/api/v1/crates/c1/reverse_dependencies"); ::mock_user(&mut req, ::user("foo")); let (c1, _) = ::mock_crate_vers(&mut req, ::krate("c1"), &v100); let _ = ::mock_crate_vers(&mut req, ::krate("c2"), &v100); @@ -1514,28 +1746,33 @@ fn author_license_and_description_required() { new_crate.authors = Vec::new(); req.with_body(&::new_crate_to_body(&new_crate, &[])); let json = bad_resp!(middle.call(&mut req)); - assert!(json.errors[0].detail.contains("author") && - json.errors[0].detail.contains("description") && + assert!( + json.errors[0].detail.contains("author") && json.errors[0].detail.contains("description") && json.errors[0].detail.contains("license"), - "{:?}", json.errors); + "{:?}", + json.errors + ); new_crate.license = Some("MIT".to_string()); new_crate.authors.push("".to_string()); req.with_body(&::new_crate_to_body(&new_crate, &[])); let json = bad_resp!(middle.call(&mut req)); - assert!(json.errors[0].detail.contains("author") && - json.errors[0].detail.contains("description") && + assert!( + json.errors[0].detail.contains("author") && json.errors[0].detail.contains("description") && !json.errors[0].detail.contains("license"), - "{:?}", json.errors); + "{:?}", + json.errors + ); new_crate.license = None; new_crate.license_file = Some("foo".to_string()); new_crate.authors.push("foo".to_string()); req.with_body(&::new_crate_to_body(&new_crate, &[])); let json = bad_resp!(middle.call(&mut req)); - assert!(!json.errors[0].detail.contains("author") && - json.errors[0].detail.contains("description") && + assert!( + !json.errors[0].detail.contains("author") && json.errors[0].detail.contains("description") && !json.errors[0].detail.contains("license"), - "{:?}", json.errors); + "{:?}", + json.errors + ); } - diff --git a/src/tests/record.rs b/src/tests/record.rs index 2a29ee01614..8e68f8c52c1 100644 --- a/src/tests/record.rs +++ b/src/tests/record.rs @@ -37,7 +37,9 @@ impl Write for Sink { fn write(&mut self, data: &[u8]) -> io::Result { Write::write(&mut *self.0.lock().unwrap(), data) } - fn flush(&mut self) -> io::Result<()> { Ok(()) } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } } impl Drop for Bomb { @@ -45,12 +47,11 @@ impl Drop for Bomb { t!(self.quit.send(())); drop(TcpStream::connect(&t!(self.accept.local_addr()))); let res = self.rx.recv(); - let stderr = str::from_utf8(&self.iorx.0.lock().unwrap()).unwrap() - .to_string(); + let stderr = str::from_utf8(&self.iorx.0.lock().unwrap()) + .unwrap() + .to_string(); match res { - Err(..) if !thread::panicking() => { - panic!("server subtask failed: {}", stderr) - } + Err(..) if !thread::panicking() => panic!("server subtask failed: {}", stderr), _ => { if stderr.len() > 0 { println!("server subtask failed: {}", stderr) @@ -61,7 +62,11 @@ impl Drop for Bomb { } fn cache_file(name: &str) -> PathBuf { - PathBuf::from(file!()).parent().unwrap().join("http-data").join(name) + PathBuf::from(file!()) + .parent() + .unwrap() + .join("http-data") + .join(name) } pub fn proxy() -> (String, Bomb) { @@ -81,38 +86,50 @@ pub fn proxy() -> (String, Bomb) { let (quittx, quitrx) = channel(); - thread::spawn(move|| { - let mut file = None; - for socket in a.incoming() { - if quitrx.try_recv().is_ok() { break } - let socket = t!(socket); + thread::spawn( + move || { + let mut file = None; + for socket in a.incoming() { + if quitrx.try_recv().is_ok() { + break; + } + let socket = t!(socket); + + if file.is_none() { + let io = t!( + if record { + File::create(&data) + } else { + File::open(&data) + } + ); + file = Some(BufStream::new(io)); + } - if file.is_none() { - let io = t!(if record { - File::create(&data) + if record { + record_http(socket, file.as_mut().unwrap()); } else { - File::open(&data) - }); - file = Some(BufStream::new(io)); - } - - if record { - record_http(socket, file.as_mut().unwrap()); - } else { - replay_http(socket, file.as_mut().unwrap(), &mut sink2); + replay_http(socket, file.as_mut().unwrap(), &mut sink2); + } } - } - if !record { - if let Some(mut f) = file { - let mut s = String::new(); - t!(f.read_line(&mut s)); - assert_eq!(s, ""); + if !record { + if let Some(mut f) = file { + let mut s = String::new(); + t!(f.read_line(&mut s)); + assert_eq!(s, ""); + } } + tx.send(()).unwrap(); } - tx.send(()).unwrap(); - }); - - (ret, Bomb { accept: a2, rx: rx, iorx: Sink(sink), quit: quittx }) + ); + + (ret, + Bomb { + accept: a2, + rx: rx, + iorx: Sink(sink), + quit: quittx, + }) } fn record_http(mut socket: TcpStream, data: &mut BufStream) { @@ -124,11 +141,16 @@ fn record_http(mut socket: TcpStream, data: &mut BufStream) { respond(handle, headers, body, &mut response); t!(socket.write_all(&response)); - t!(write!(data, "===REQUEST {}\n{}\n===RESPONSE {}\n{}\n", - request.len(), - str::from_utf8(&request).unwrap(), - response.len(), - str::from_utf8(&response).unwrap())); + t!( + write!( + data, + "===REQUEST {}\n{}\n===RESPONSE {}\n{}\n", + request.len(), + str::from_utf8(&request).unwrap(), + response.len(), + str::from_utf8(&response).unwrap() + ) + ); fn send(rdr: R) -> (Easy, Vec>, Vec) { let mut socket = BufReader::new(rdr); @@ -145,7 +167,7 @@ fn record_http(mut socket: TcpStream, data: &mut BufStream) { for line in lines { let line = t!(line); if line.len() < 3 { - break + break; } t!(headers.append(&line)); } @@ -165,17 +187,23 @@ fn record_http(mut socket: TcpStream, data: &mut BufStream) { let mut response = Vec::new(); { let mut transfer = handle.transfer(); - t!(transfer.header_function(|header| { - headers.push(header.to_owned()); - true - })); - t!(transfer.write_function(|data| { - response.extend(data); - Ok(data.len()) - })); - t!(transfer.read_function(|buf| { - socket.read(buf).map_err(|_| ReadError::Abort) - })); + t!( + transfer.header_function( + |header| { + headers.push(header.to_owned()); + true + } + ) + ); + t!( + transfer.write_function( + |data| { + response.extend(data); + Ok(data.len()) + } + ) + ); + t!(transfer.read_function(|buf| socket.read(buf).map_err(|_| ReadError::Abort))); t!(transfer.perform()); } @@ -183,15 +211,11 @@ fn record_http(mut socket: TcpStream, data: &mut BufStream) { (handle, headers, response) } - fn respond(mut handle: Easy, - headers: Vec>, - body: Vec, - mut socket: W) { - t!(socket.write_all(format!("HTTP/1.1 {}\r\n", - t!(handle.response_code())).as_bytes())); + fn respond(mut handle: Easy, headers: Vec>, body: Vec, mut socket: W) { + t!(socket.write_all(format!("HTTP/1.1 {}\r\n", t!(handle.response_code())).as_bytes())); for header in headers { if header.starts_with(b"Transfer-Encoding: ") { - continue + continue; } t!(socket.write_all(&header)); t!(socket.write_all(b"\r\n")); @@ -201,8 +225,7 @@ fn record_http(mut socket: TcpStream, data: &mut BufStream) { } } -fn replay_http(socket: TcpStream, data: &mut BufStream, - stdout: &mut Write) { +fn replay_http(socket: TcpStream, data: &mut BufStream, stdout: &mut Write) { let mut writer = socket.try_clone().unwrap(); let socket = BufReader::new(socket); @@ -218,22 +241,35 @@ fn replay_http(socket: TcpStream, data: &mut BufStream, let mut actual_lines = socket.lines().map(|s| s.unwrap()); // validate the headers - let mut expected: HashSet = expected_lines.by_ref() - .take_while(|l| l.len() > 2) - .collect(); + let mut expected: HashSet = expected_lines + .by_ref() + .take_while(|l| l.len() > 2) + .collect(); let mut found = HashSet::new(); t!(writeln!(stdout, "expecting: {:?}", expected)); for line in actual_lines.by_ref().take_while(|l| l.len() > 2) { t!(writeln!(stdout, "received: {}", line.trim())); - if !found.insert(line.clone()) { continue } - if expected.remove(&line) { continue } - if line.starts_with("Date:") { continue } - if line.starts_with("Authorization:") { continue } + if !found.insert(line.clone()) { + continue; + } + if expected.remove(&line) { + continue; + } + if line.starts_with("Date:") { + continue; + } + if line.starts_with("Authorization:") { + continue; + } panic!("unexpected header: {}", line); } for line in expected.iter() { - if line.starts_with("Date:") { continue } - if line.starts_with("Authorization:") { continue } + if line.starts_with("Date:") { + continue; + } + if line.starts_with("Authorization:") { + continue; + } panic!("didn't receive header: {}", line); } @@ -247,10 +283,11 @@ fn replay_http(socket: TcpStream, data: &mut BufStream, let response_size = response.next().unwrap().trim().parse().unwrap(); let mut response = Vec::new(); data.take(response_size).read_to_end(&mut response).unwrap(); - let lines = <[_]>::split(&response[..], |b| *b == b'\n') - .map(|s| str::from_utf8(s).unwrap()); + let lines = <[_]>::split(&response[..], |b| *b == b'\n').map(|s| str::from_utf8(s).unwrap()); for line in lines { - if line.starts_with("Date:") { continue } + if line.starts_with("Date:") { + continue; + } writer.write_all(line.as_bytes()).unwrap(); writer.write_all(b"\r\n").unwrap(); } @@ -262,22 +299,28 @@ impl GhUser { self.init.call_once(|| self.init()); let mut u = ::new_user(self.login); u.gh_access_token = Cow::Owned(self.token()); - return u + return u; } - fn filename(&self) -> PathBuf { cache_file(&format!("gh-{}", self.login)) } + fn filename(&self) -> PathBuf { + cache_file(&format!("gh-{}", self.login)) + } fn token(&self) -> String { let mut token = String::new(); - File::open(&self.filename()).unwrap().read_to_string(&mut token).unwrap(); - return token + File::open(&self.filename()) + .unwrap() + .read_to_string(&mut token) + .unwrap(); + return token; } fn init(&self) { - if fs::metadata(&self.filename()).is_ok() { return } + if fs::metadata(&self.filename()).is_ok() { + return; + } - let password = ::env(&format!("GH_PASS_{}", - self.login.replace("-", "_"))); + let password = ::env(&format!("GH_PASS_{}", self.login.replace("-", "_"))); #[derive(RustcEncodable)] struct Authorization { scopes: Vec, @@ -286,14 +329,20 @@ impl GhUser { client_secret: String, } let mut handle = Easy::new(); - let url = format!("https://{}:{}@api.github.com/authorizations", - self.login, password); - let body = json::encode(&Authorization { - scopes: vec!["read:org".to_string()], - note: "crates.io test".to_string(), - client_id: ::env("GH_CLIENT_ID"), - client_secret: ::env("GH_CLIENT_SECRET"), - }).unwrap(); + let url = format!( + "https://{}:{}@api.github.com/authorizations", + self.login, + password + ); + let body = json::encode( + &Authorization { + scopes: vec!["read:org".to_string()], + note: "crates.io test".to_string(), + client_id: ::env("GH_CLIENT_ID"), + client_secret: ::env("GH_CLIENT_SECRET"), + } + ) + .unwrap(); t!(handle.url(&url)); t!(handle.post(true)); @@ -306,26 +355,30 @@ impl GhUser { let mut response = Vec::new(); { let mut transfer = handle.transfer(); - t!(transfer.read_function(|buf| { - body.read(buf).map_err(|_| ReadError::Abort) - })); - t!(transfer.write_function(|data| { - response.extend(data); - Ok(data.len()) - })); + t!(transfer.read_function(|buf| body.read(buf).map_err(|_| ReadError::Abort))); + t!( + transfer.write_function( + |data| { + response.extend(data); + Ok(data.len()) + } + ) + ); t!(transfer.perform()) } if t!(handle.response_code()) < 200 || t!(handle.response_code()) >= 300 { - panic!("failed to get a 200 {}", - String::from_utf8_lossy(&response)); + panic!("failed to get a 200 {}", String::from_utf8_lossy(&response)); } #[derive(RustcDecodable)] - struct Response { token: String } - let resp: Response = json::decode(str::from_utf8(&response) - .unwrap()).unwrap(); - File::create(&self.filename()).unwrap() - .write_all(&resp.token.as_bytes()).unwrap(); + struct Response { + token: String, + } + let resp: Response = json::decode(str::from_utf8(&response).unwrap()).unwrap(); + File::create(&self.filename()) + .unwrap() + .write_all(&resp.token.as_bytes()) + .unwrap(); } } diff --git a/src/tests/team.rs b/src/tests/team.rs index 52ff6f5d135..29b35b243db 100644 --- a/src/tests/team.rs +++ b/src/tests/team.rs @@ -9,11 +9,21 @@ use record::GhUser; // Teams: `crates-test-org:owners`, `crates-test-org:just-for-crates-2` // tester-1 is on owners only, tester-2 is on both -static GH_USER_1: GhUser = GhUser { login: "crates-tester-1", init: ONCE_INIT }; -static GH_USER_2: GhUser = GhUser { login: "crates-tester-2", init: ONCE_INIT }; - -fn mock_user_on_only_x() -> NewUser<'static> { GH_USER_1.user() } -fn mock_user_on_x_and_y() -> NewUser<'static> { GH_USER_2.user() } +static GH_USER_1: GhUser = GhUser { + login: "crates-tester-1", + init: ONCE_INIT, +}; +static GH_USER_2: GhUser = GhUser { + login: "crates-tester-2", + init: ONCE_INIT, +}; + +fn mock_user_on_only_x() -> NewUser<'static> { + GH_USER_1.user() +} +fn mock_user_on_x_and_y() -> NewUser<'static> { + GH_USER_2.user() +} fn body_for_team_y() -> &'static str { r#"{"users":["github:crates-test-org:just-for-crates-2"]}"# @@ -27,103 +37,147 @@ fn body_for_team_x() -> &'static str { #[test] fn not_github() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_x_and_y(), "foo_not_github"); + let mut req = ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_not_github"); let body = r#"{"users":["dropbox:foo:foo"]}"#; - let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_not_github/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); - assert!(json.errors[0].detail.contains("unknown organization"), - "{:?}", json.errors); + let json = bad_resp!( + middle.call( + req.with_path("/api/v1/crates/foo_not_github/owners") + .with_method(Method::Put) + .with_body(body.as_bytes()) + ) + ); + assert!( + json.errors[0].detail.contains("unknown organization"), + "{:?}", + json.errors + ); } #[test] fn weird_name() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_x_and_y(), "foo_weird_name"); + let mut req = ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_weird_name"); let body = r#"{"users":["github:foo/../bar:wut"]}"#; - let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_weird_name/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); - assert!(json.errors[0].detail.contains("organization cannot contain"), - "{:?}", json.errors); + let json = bad_resp!( + middle.call( + req.with_path("/api/v1/crates/foo_weird_name/owners") + .with_method(Method::Put) + .with_body(body.as_bytes()) + ) + ); + assert!( + json.errors[0] + .detail + .contains("organization cannot contain"), + "{:?}", + json.errors + ); } // Test adding team without second `:` #[test] fn one_colon() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_x_and_y(), "foo_one_colon"); + let mut req = ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_one_colon"); let body = r#"{"users":["github:foo"]}"#; - let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_one_colon/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); - assert!(json.errors[0].detail.contains("missing github team"), - "{:?}", json.errors); + let json = bad_resp!( + middle.call( + req.with_path("/api/v1/crates/foo_one_colon/owners") + .with_method(Method::Put) + .with_body(body.as_bytes()) + ) + ); + assert!( + json.errors[0].detail.contains("missing github team"), + "{:?}", + json.errors + ); } #[test] fn nonexistent_team() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_x_and_y(), "foo_nonexistent"); + let mut req = ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_nonexistent"); let body = r#"{"users":["github:crates-test-org:this-does-not-exist"]}"#; - let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_nonexistent/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); - assert!(json.errors[0].detail.contains("could not find the github team"), - "{:?}", json.errors); + let json = bad_resp!( + middle.call( + req.with_path("/api/v1/crates/foo_nonexistent/owners") + .with_method(Method::Put) + .with_body(body.as_bytes()) + ) + ); + assert!( + json.errors[0] + .detail + .contains("could not find the github team"), + "{:?}", + json.errors + ); } // Test adding team as owner when on it #[test] fn add_team_as_member() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_x_and_y(), "foo_team_member"); + let mut req = ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_team_member"); let body = body_for_team_x(); - ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_team_member/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + ok_resp!( + middle.call( + req.with_path("/api/v1/crates/foo_team_member/owners") + .with_method(Method::Put) + .with_body(body.as_bytes()) + ) + ); } // Test adding team as owner when not on in #[test] fn add_team_as_non_member() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_only_x(), "foo_team_non_member"); + let mut req = ::request_with_user_and_mock_crate(&app, mock_user_on_only_x(), "foo_team_non_member"); let body = body_for_team_y(); - let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_team_non_member/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); - assert!(json.errors[0].detail.contains("only members"), - "{:?}", json.errors); + let json = bad_resp!( + middle.call( + req.with_path("/api/v1/crates/foo_team_non_member/owners") + .with_method(Method::Put) + .with_body(body.as_bytes()) + ) + ); + assert!( + json.errors[0].detail.contains("only members"), + "{:?}", + json.errors + ); } #[test] fn remove_team_as_named_owner() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_x_and_y(), "foo_remove_team"); + let mut req = ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_remove_team"); let body = body_for_team_x(); - ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_remove_team/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + ok_resp!( + middle.call( + req.with_path("/api/v1/crates/foo_remove_team/owners") + .with_method(Method::Put) + .with_body(body.as_bytes()) + ) + ); let body = body_for_team_x(); - ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_remove_team/owners") - .with_method(Method::Delete) - .with_body(body.as_bytes()))); + ok_resp!( + middle.call( + req.with_path("/api/v1/crates/foo_remove_team/owners") + .with_method(Method::Delete) + .with_body(body.as_bytes()) + ) + ); { let conn = app.diesel_database.get().unwrap(); @@ -131,23 +185,33 @@ fn remove_team_as_named_owner() { ::sign_in_as(&mut req, &user); } let body = ::new_req_body_version_2(::krate("foo_remove_team")); - let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_body(&body) - .with_method(Method::Put))); - assert!(json.errors[0].detail.contains("another user"), - "{:?}", json.errors); + let json = bad_resp!( + middle.call( + req.with_path("/api/v1/crates/new") + .with_body(&body) + .with_method(Method::Put) + ) + ); + assert!( + json.errors[0].detail.contains("another user"), + "{:?}", + json.errors + ); } #[test] fn remove_team_as_team_owner() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_x_and_y(), "foo_remove_team_owner"); + let mut req = ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_remove_team_owner"); let body = body_for_team_x(); - ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_remove_team_owner/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + ok_resp!( + middle.call( + req.with_path("/api/v1/crates/foo_remove_team_owner/owners") + .with_method(Method::Put) + .with_body(body.as_bytes()) + ) + ); { let conn = app.diesel_database.get().unwrap(); @@ -155,17 +219,28 @@ fn remove_team_as_team_owner() { ::sign_in_as(&mut req, &user); } let body = body_for_team_x(); - let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_remove_team_owner/owners") - .with_method(Method::Delete) - .with_body(body.as_bytes()))); - - assert!(json.errors[0].detail.contains("don't have permission"), - "{:?}", json.errors); + let json = bad_resp!( + middle.call( + req.with_path("/api/v1/crates/foo_remove_team_owner/owners") + .with_method(Method::Delete) + .with_body(body.as_bytes()) + ) + ); + + assert!( + json.errors[0].detail.contains("don't have permission"), + "{:?}", + json.errors + ); let body = ::new_req_body_version_2(::krate("foo_remove_team_owner")); - ok_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_body(&body) - .with_method(Method::Put))); + ok_resp!( + middle.call( + req.with_path("/api/v1/crates/new") + .with_body(&body) + .with_method(Method::Put) + ) + ); } // Test trying to publish a krate we don't own @@ -173,13 +248,16 @@ fn remove_team_as_team_owner() { fn publish_not_owned() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_x_and_y(), "foo_not_owned"); + let mut req = ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_not_owned"); let body = body_for_team_y(); - ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_not_owned/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + ok_resp!( + middle.call( + req.with_path("/api/v1/crates/foo_not_owned/owners") + .with_method(Method::Put) + .with_body(body.as_bytes()) + ) + ); { let conn = app.diesel_database.get().unwrap(); @@ -187,24 +265,34 @@ fn publish_not_owned() { ::sign_in_as(&mut req, &user); } let body = ::new_req_body_version_2(::krate("foo_not_owned")); - let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_body(&body) - .with_method(Method::Put))); - assert!(json.errors[0].detail.contains("another user"), - "{:?}", json.errors); + let json = bad_resp!( + middle.call( + req.with_path("/api/v1/crates/new") + .with_body(&body) + .with_method(Method::Put) + ) + ); + assert!( + json.errors[0].detail.contains("another user"), + "{:?}", + json.errors + ); } // Test trying to publish a krate we do own (but only because of teams) #[test] fn publish_owned() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_x_and_y(), "foo_team_owned"); + let mut req = ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_team_owned"); let body = body_for_team_x(); - ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_team_owned/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + ok_resp!( + middle.call( + req.with_path("/api/v1/crates/foo_team_owned/owners") + .with_method(Method::Put) + .with_body(body.as_bytes()) + ) + ); { let conn = app.diesel_database.get().unwrap(); @@ -212,32 +300,46 @@ fn publish_owned() { ::sign_in_as(&mut req, &user); } let body = ::new_req_body_version_2(::krate("foo_team_owned")); - ok_resp!(middle.call(req.with_path("/api/v1/crates/new") - .with_body(&body) - .with_method(Method::Put))); + ok_resp!( + middle.call( + req.with_path("/api/v1/crates/new") + .with_body(&body) + .with_method(Method::Put) + ) + ); } // Test trying to change owners (when only on an owning team) #[test] fn add_owners_as_team_owner() { let (_b, app, middle) = ::app(); - let mut req = ::request_with_user_and_mock_crate( - &app, mock_user_on_x_and_y(), "foo_add_owner"); + let mut req = ::request_with_user_and_mock_crate(&app, mock_user_on_x_and_y(), "foo_add_owner"); let body = body_for_team_x(); - ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_add_owner/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); + ok_resp!( + middle.call( + req.with_path("/api/v1/crates/foo_add_owner/owners") + .with_method(Method::Put) + .with_body(body.as_bytes()) + ) + ); { let conn = app.diesel_database.get().unwrap(); let user = mock_user_on_only_x().create_or_update(&conn).unwrap(); ::sign_in_as(&mut req, &user); } - let body = r#"{"users":["FlashCat"]}"#; // User doesn't matter - let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo_add_owner/owners") - .with_method(Method::Put) - .with_body(body.as_bytes()))); - assert!(json.errors[0].detail.contains("don't have permission"), - "{:?}", json.errors); + let body = r#"{"users":["FlashCat"]}"#; // User doesn't matter + let json = bad_resp!( + middle.call( + req.with_path("/api/v1/crates/foo_add_owner/owners") + .with_method(Method::Put) + .with_body(body.as_bytes()) + ) + ); + assert!( + json.errors[0].detail.contains("don't have permission"), + "{:?}", + json.errors + ); } diff --git a/src/tests/user.rs b/src/tests/user.rs index 2372eec8c34..8c25b8581c2 100644 --- a/src/tests/user.rs +++ b/src/tests/user.rs @@ -7,11 +7,19 @@ use cargo_registry::user::{User, NewUser, EncodableUser}; use cargo_registry::version::EncodableVersion; #[derive(RustcDecodable)] -struct AuthResponse { url: String, state: String } +struct AuthResponse { + url: String, + state: String, +} #[derive(RustcDecodable)] -struct MeResponse { user: EncodableUser, api_token: String } +struct MeResponse { + user: EncodableUser, + api_token: String, +} #[derive(RustcDecodable)] -struct UserShowResponse { user: EncodableUser } +struct UserShowResponse { + user: EncodableUser, +} #[test] fn auth_gives_a_token() { @@ -41,16 +49,16 @@ fn user_insert() { assert_eq!(t!(User::find_by_api_token(&tx, &user.api_token)), user); assert_eq!(t!(User::find(&tx, user.id)), user); - assert_eq!(t!(User::find_or_insert(&tx, 1, "foo", None, None, None, - "bar")), user); - let user2 = t!(User::find_or_insert(&tx, 1, "foo", None, None, None, - "baz")); + assert_eq!( + t!(User::find_or_insert(&tx, 1, "foo", None, None, None, "bar")), + user + ); + let user2 = t!(User::find_or_insert(&tx, 1, "foo", None, None, None, "baz")); assert!(user != user2); assert_eq!(user.id, user2.id); assert_eq!(user2.gh_access_token, "baz"); - let user3 = t!(User::find_or_insert(&tx, 1, "bar", None, None, None, - "baz")); + let user3 = t!(User::find_or_insert(&tx, 1, "bar", None, None, None, "baz")); assert!(user != user3); assert_eq!(user.id, user3.id); assert_eq!(user3.gh_login, "bar"); @@ -97,8 +105,7 @@ fn show() { fn reset_token() { let (_b, app, middle) = ::app(); let mut req = ::req(app, Method::Put, "/me/reset_token"); - let user = User::find_or_insert(req.tx().unwrap(), 1, "foo", None, - None, None, "bar").unwrap(); + let user = User::find_or_insert(req.tx().unwrap(), 1, "foo", None, None, None, "bar").unwrap(); ::sign_in_as(&mut req, &user); ok_resp!(middle.call(&mut req)); @@ -112,11 +119,8 @@ fn crates_by_user_id() { let u; { let conn = app.diesel_database.get().unwrap(); - u = ::new_user("foo") - .create_or_update(&conn) - .unwrap(); - ::CrateBuilder::new("foo_my_packages", u.id) - .expect_build(&conn); + u = ::new_user("foo").create_or_update(&conn).unwrap(); + ::CrateBuilder::new("foo_my_packages", u.id).expect_build(&conn); } let mut req = ::req(app, Method::Get, "/api/v1/crates"); @@ -124,7 +128,9 @@ fn crates_by_user_id() { let mut response = ok_resp!(middle.call(&mut req)); #[derive(RustcDecodable)] - struct Response { crates: Vec } + struct Response { + crates: Vec, + } let response: Response = ::json(&mut response); assert_eq!(response.crates.len(), 1); } @@ -136,7 +142,10 @@ fn following() { versions: Vec, meta: Meta, } - #[derive(RustcDecodable)] struct Meta { more: bool } + #[derive(RustcDecodable)] + struct Meta { + more: bool, + } let (_b, app, middle) = ::app(); let mut req = ::req(app.clone(), Method::Get, "/"); @@ -154,35 +163,53 @@ fn following() { .expect_build(&conn); } - let mut response = ok_resp!(middle.call(req.with_path("/me/updates") - .with_method(Method::Get))); + let mut response = ok_resp!(middle.call(req.with_path("/me/updates").with_method(Method::Get))); let r = ::json::(&mut response); assert_eq!(r.versions.len(), 0); assert_eq!(r.meta.more, false); - ok_resp!(middle.call(req.with_path("/api/v1/crates/foo_fighters/follow") - .with_method(Method::Put))); - ok_resp!(middle.call(req.with_path("/api/v1/crates/bar_fighters/follow") - .with_method(Method::Put))); - - let mut response = ok_resp!(middle.call(req.with_path("/me/updates") - .with_method(Method::Get))); + ok_resp!( + middle.call( + req.with_path("/api/v1/crates/foo_fighters/follow") + .with_method(Method::Put) + ) + ); + ok_resp!( + middle.call( + req.with_path("/api/v1/crates/bar_fighters/follow") + .with_method(Method::Put) + ) + ); + + let mut response = ok_resp!(middle.call(req.with_path("/me/updates").with_method(Method::Get))); let r = ::json::(&mut response); assert_eq!(r.versions.len(), 2); assert_eq!(r.meta.more, false); - let mut response = ok_resp!(middle.call(req.with_path("/me/updates") - .with_method(Method::Get) - .with_query("per_page=1"))); + let mut response = ok_resp!( + middle.call( + req.with_path("/me/updates") + .with_method(Method::Get) + .with_query("per_page=1") + ) + ); let r = ::json::(&mut response); assert_eq!(r.versions.len(), 1); assert_eq!(r.meta.more, true); - ok_resp!(middle.call(req.with_path("/api/v1/crates/bar_fighters/follow") - .with_method(Method::Delete))); - let mut response = ok_resp!(middle.call(req.with_path("/me/updates") - .with_method(Method::Get) - .with_query("page=2&per_page=1"))); + ok_resp!( + middle.call( + req.with_path("/api/v1/crates/bar_fighters/follow") + .with_method(Method::Delete) + ) + ); + let mut response = ok_resp!( + middle.call( + req.with_path("/me/updates") + .with_method(Method::Get) + .with_query("page=2&per_page=1") + ) + ); let r = ::json::(&mut response); assert_eq!(r.versions.len(), 0); assert_eq!(r.meta.more, false); diff --git a/src/tests/version.rs b/src/tests/version.rs index 00501ed7449..db8851d1447 100644 --- a/src/tests/version.rs +++ b/src/tests/version.rs @@ -8,9 +8,13 @@ use cargo_registry::db::RequestTransaction; use cargo_registry::version::{EncodableVersion, Version}; #[derive(RustcDecodable)] -struct VersionList { versions: Vec } +struct VersionList { + versions: Vec, +} #[derive(RustcDecodable)] -struct VersionResponse { version: EncodableVersion } +struct VersionResponse { + version: EncodableVersion, +} fn sv(s: &str) -> semver::Version { semver::Version::parse(s).unwrap() @@ -46,8 +50,7 @@ fn show() { let v = { let conn = app.diesel_database.get().unwrap(); let user = ::new_user("foo").create_or_update(&conn).unwrap(); - let krate = ::CrateBuilder::new("foo_vers_show", user.id) - .expect_build(&conn); + let krate = ::CrateBuilder::new("foo_vers_show", user.id).expect_build(&conn); ::new_version(krate.id, "2.0.0").save(&conn, &[]).unwrap() }; req.with_path(&format!("/api/v1/versions/{}", v.id)); diff --git a/src/upload.rs b/src/upload.rs index 7c64b456bf2..730e0caed78 100644 --- a/src/upload.rs +++ b/src/upload.rs @@ -52,16 +52,21 @@ impl Decodable for CrateName { fn decode(d: &mut D) -> Result { let s = d.read_str()?; if !Crate::valid_name(&s) { - return Err(d.error(&format!("invalid crate name specified: {}. \ + return Err( + d.error( + &format!("invalid crate name specified: {}. \ Valid crate names must start with a letter; contain only \ letters, numbers, hyphens, or underscores; and have {} or \ - fewer characters.", s, MAX_NAME_LENGTH))) + fewer characters.", s, MAX_NAME_LENGTH) + ) + ); } Ok(CrateName(s)) } } -impl PartialEq for CrateName where +impl PartialEq for CrateName +where String: PartialEq, { fn eq(&self, rhs: &T) -> bool { @@ -73,7 +78,7 @@ impl Decodable for Keyword { fn decode(d: &mut D) -> Result { let s = d.read_str()?; if !CrateKeyword::valid_name(&s) { - return Err(d.error(&format!("invalid keyword specified: {}", s))) + return Err(d.error(&format!("invalid keyword specified: {}", s))); } Ok(Keyword(s)) } @@ -89,7 +94,7 @@ impl Decodable for Feature { fn decode(d: &mut D) -> Result { let s = d.read_str()?; if !Crate::valid_feature_name(&s) { - return Err(d.error(&format!("invalid feature name specified: {}", s))) + return Err(d.error(&format!("invalid feature name specified: {}", s))); } Ok(Feature(s)) } @@ -115,7 +120,8 @@ impl Decodable for CrateVersionReq { } } -impl PartialEq for CrateVersionReq where +impl PartialEq for CrateVersionReq +where semver::VersionReq: PartialEq, { fn eq(&self, rhs: &T) -> bool { @@ -127,12 +133,16 @@ impl Decodable for KeywordList { fn decode(d: &mut D) -> Result { let inner: Vec = Decodable::decode(d)?; if inner.len() > 5 { - return Err(d.error("a maximum of 5 keywords per crate are allowed")) + return Err(d.error("a maximum of 5 keywords per crate are allowed")); } for val in &inner { if val.len() > 20 { - return Err(d.error("keywords must contain less than 20 \ - characters")) + return Err( + d.error( + "keywords must contain less than 20 \ + characters" + ) + ); } } Ok(KeywordList(inner)) @@ -143,7 +153,7 @@ impl Decodable for CategoryList { fn decode(d: &mut D) -> Result { let inner: Vec = Decodable::decode(d)?; if inner.len() > 5 { - return Err(d.error("a maximum of 5 categories per crate are allowed")) + return Err(d.error("a maximum of 5 categories per crate are allowed")); } Ok(CategoryList(inner)) } @@ -156,8 +166,14 @@ impl Decodable for DependencyKind { "dev" => Ok(DependencyKind::Dev), "build" => Ok(DependencyKind::Build), "normal" => Ok(DependencyKind::Normal), - s => Err(d.error(&format!("invalid dependency kind `{}`, must be \ - one of dev, build, or normal", s))), + s => { + Err( + d.error( + &format!("invalid dependency kind `{}`, must be \ + one of dev, build, or normal", s) + ) + ) + } } } } @@ -224,40 +240,56 @@ impl Encodable for DependencyKind { impl Deref for CrateName { type Target = str; - fn deref(&self) -> &str { &self.0 } + fn deref(&self) -> &str { + &self.0 + } } impl Deref for Keyword { type Target = str; - fn deref(&self) -> &str { &self.0 } + fn deref(&self) -> &str { + &self.0 + } } impl Deref for Category { type Target = str; - fn deref(&self) -> &str { &self.0 } + fn deref(&self) -> &str { + &self.0 + } } impl Deref for Feature { type Target = str; - fn deref(&self) -> &str { &self.0 } + fn deref(&self) -> &str { + &self.0 + } } impl Deref for CrateVersion { type Target = semver::Version; - fn deref(&self) -> &semver::Version { &self.0 } + fn deref(&self) -> &semver::Version { + &self.0 + } } impl Deref for CrateVersionReq { type Target = semver::VersionReq; - fn deref(&self) -> &semver::VersionReq { &self.0 } + fn deref(&self) -> &semver::VersionReq { + &self.0 + } } impl Deref for KeywordList { type Target = [Keyword]; - fn deref(&self) -> &[Keyword] { &self.0 } + fn deref(&self) -> &[Keyword] { + &self.0 + } } impl Deref for CategoryList { type Target = [Category]; - fn deref(&self) -> &[Category] { &self.0 } + fn deref(&self) -> &[Category] { + &self.0 + } } diff --git a/src/uploaders.rs b/src/uploaders.rs index f31e045bb20..76f481aaa61 100644 --- a/src/uploaders.rs +++ b/src/uploaders.rs @@ -14,7 +14,10 @@ use std::io; pub enum Uploader { /// For production usage, uploads and redirects to s3. /// For test usage with a proxy. - S3 { bucket: s3::Bucket, proxy: Option }, + S3 { + bucket: s3::Bucket, + proxy: Option, + }, /// For development usage only: "uploads" crate files to `dist` and serves them /// from there as well to enable local publishing and download @@ -32,17 +35,20 @@ impl Uploader { } } - pub fn crate_location(&self, crate_name: &str, version: &str) - -> Option { + pub fn crate_location(&self, crate_name: &str, version: &str) -> Option { match *self { Uploader::S3 { ref bucket, .. } => { - Some(format!("https://{}/{}", + Some( + format!("https://{}/{}", bucket.host(), - Uploader::crate_path(crate_name, version))) - }, + Uploader::crate_path(crate_name, version)) + ) + } Uploader::Local => { - Some(format!("/local_uploads/{}", - Uploader::crate_path(crate_name, version))) + Some( + format!("/local_uploads/{}", + Uploader::crate_path(crate_name, version)) + ) } Uploader::NoOp => None, } @@ -64,36 +70,52 @@ impl Uploader { let mut body = HashingReader::new(body); let mut response = Vec::new(); { - let mut s3req = bucket.put(&mut handle, &path, &mut body, - "application/x-tar", - length as u64); - s3req.write_function(|data| { - response.extend(data); - Ok(data.len()) - }).unwrap(); - s3req.perform().chain_error(|| { - internal(&format_args!("failed to upload to S3: `{}`", path)) - })?; + let mut s3req = bucket.put( + &mut handle, + &path, + &mut body, + "application/x-tar", + length as u64, + ); + s3req + .write_function( + |data| { + response.extend(data); + Ok(data.len()) + } + ) + .unwrap(); + s3req + .perform() + .chain_error(|| internal(&format_args!("failed to upload to S3: `{}`", path)))?; } (response, body.finalize()) }; if handle.response_code().unwrap() != 200 { let response = String::from_utf8_lossy(&response); - return Err(internal(&format_args!("failed to get a 200 response from S3: {}", - response))) + return Err( + internal( + &format_args!("failed to get a 200 response from S3: {}", + response) + ) + ); } - Ok((cksum, Bomb { - app: req.app().clone(), - path: Some(path), - })) - }, + Ok( + (cksum, + Bomb { + app: req.app().clone(), + path: Some(path), + }) + ) + } Uploader::Local => { let path = Uploader::crate_path(&krate.name, &vers.to_string()); - let crate_filename = env::current_dir().unwrap() - .join("dist") - .join("local_uploads") - .join(path); + let crate_filename = env::current_dir() + .unwrap() + .join("dist") + .join("local_uploads") + .join(path); let crate_dir = crate_filename.parent().unwrap(); fs::create_dir_all(crate_dir)?; @@ -109,12 +131,23 @@ impl Uploader { body.finalize() }; - Ok((cksum, Bomb { - app: req.app().clone(), - path: crate_filename.to_str().map(String::from) - })) - }, - Uploader::NoOp => Ok((vec![], Bomb { app: req.app().clone(), path: None })), + Ok( + (cksum, + Bomb { + app: req.app().clone(), + path: crate_filename.to_str().map(String::from), + }) + ) + } + Uploader::NoOp => { + Ok( + (vec![], + Bomb { + app: req.app().clone(), + path: None, + }) + ) + } } } @@ -124,7 +157,7 @@ impl Uploader { let mut handle = app.handle(); bucket.delete(&mut handle, path).perform()?; Ok(()) - }, + } Uploader::Local => { fs::remove_file(path)?; Ok(()) diff --git a/src/user/middleware.rs b/src/user/middleware.rs index 43959aea975..2b5b256b606 100644 --- a/src/user/middleware.rs +++ b/src/user/middleware.rs @@ -12,9 +12,11 @@ use util::errors::{CargoResult, Unauthorized, ChainError, std_error}; pub struct Middleware; impl conduit_middleware::Middleware for Middleware { - fn before(&self, req: &mut Request) -> Result<(), Box> { + fn before(&self, req: &mut Request) -> Result<(), Box> { // Check if the request has a session cookie with a `user_id` property inside - let id = { req.session().get("user_id").and_then(|s| s.parse().ok()) }; + let id = { + req.session().get("user_id").and_then(|s| s.parse().ok()) + }; let user = match id { @@ -39,10 +41,10 @@ impl conduit_middleware::Middleware for Middleware { let tx = req.tx().map_err(std_error)?; match User::find_by_api_token(tx, headers[0]) { Ok(user) => user, - Err(..) => return Ok(()) + Err(..) => return Ok(()), } } - None => return Ok(()) + None => return Ok(()), } } }; @@ -59,6 +61,8 @@ pub trait RequestUser { impl<'a> RequestUser for Request + 'a { fn user(&self) -> CargoResult<&User> { - self.extensions().find::().chain_error(|| Unauthorized) + self.extensions() + .find::() + .chain_error(|| Unauthorized) } } diff --git a/src/user/mod.rs b/src/user/mod.rs index d6359cc7c37..d44c42f3edf 100644 --- a/src/user/mod.rs +++ b/src/user/mod.rs @@ -1,5 +1,5 @@ use conduit::{Request, Response}; -use conduit_cookie::{RequestSession}; +use conduit_cookie::RequestSession; use conduit_router::RequestParams; use diesel::prelude::*; use diesel::pg::PgConnection; @@ -46,12 +46,14 @@ pub struct NewUser<'a> { } impl<'a> NewUser<'a> { - pub fn new(gh_id: i32, - gh_login: &'a str, - email: Option<&'a str>, - name: Option<&'a str>, - gh_avatar: Option<&'a str>, - gh_access_token: &'a str) -> Self { + pub fn new( + gh_id: i32, + gh_login: &'a str, + email: Option<&'a str>, + name: Option<&'a str>, + gh_avatar: Option<&'a str>, + gh_access_token: &'a str, + ) -> Self { NewUser { gh_id: gh_id, gh_login: gh_login, @@ -90,76 +92,84 @@ pub struct EncodableUser { impl User { /// Queries the database for a user with a certain `gh_login` value. - pub fn find_by_login(conn: &GenericConnection, - login: &str) -> CargoResult { - let stmt = conn.prepare("SELECT * FROM users - WHERE gh_login = $1")?; + pub fn find_by_login(conn: &GenericConnection, login: &str) -> CargoResult { + let stmt = conn.prepare( + "SELECT * FROM users + WHERE gh_login = $1" + )?; let rows = stmt.query(&[&login])?; - let row = rows.iter().next().chain_error(|| { - NotFound - })?; + let row = rows.iter().next().chain_error(|| NotFound)?; Ok(Model::from_row(&row)) } /// Queries the database for a user with a certain `api_token` value. - pub fn find_by_api_token(conn: &GenericConnection, - token: &str) -> CargoResult { - let stmt = conn.prepare("SELECT * FROM users \ - WHERE api_token = $1 LIMIT 1")?; + pub fn find_by_api_token(conn: &GenericConnection, token: &str) -> CargoResult { + let stmt = conn.prepare( + "SELECT * FROM users \ + WHERE api_token = $1 LIMIT 1" + )?; let rows = stmt.query(&[&token])?; - rows.iter().next().map(|r| Model::from_row(&r)).chain_error(|| { - NotFound - }) + rows.iter() + .next() + .map(|r| Model::from_row(&r)) + .chain_error(|| NotFound) } /// Updates a user or inserts a new user into the database. - pub fn find_or_insert(conn: &GenericConnection, - id: i32, - login: &str, - email: Option<&str>, - name: Option<&str>, - avatar: Option<&str>, - access_token: &str) -> CargoResult { + pub fn find_or_insert( + conn: &GenericConnection, + id: i32, + login: &str, + email: Option<&str>, + name: Option<&str>, + avatar: Option<&str>, + access_token: &str, + ) -> CargoResult { // TODO: this is racy, but it looks like any other solution is... // interesting! For now just do the racy thing which will report // more errors than it needs to. - let stmt = conn.prepare("UPDATE users + let stmt = conn.prepare( + "UPDATE users SET gh_access_token = $1, email = $2, name = $3, gh_avatar = $4, gh_login = $5 WHERE gh_id = $6 - RETURNING *")?; - let rows = stmt.query(&[&access_token, - &email, - &name, - &avatar, - &login, - &id])?; + RETURNING *" + )?; + let rows = stmt.query(&[&access_token, &email, &name, &avatar, &login, &id])?; if let Some(ref row) = rows.iter().next() { return Ok(Model::from_row(row)); } - let stmt = conn.prepare("INSERT INTO users + let stmt = conn.prepare( + "INSERT INTO users (email, gh_access_token, gh_login, name, gh_avatar, gh_id) VALUES ($1, $2, $3, $4, $5, $6) - RETURNING *")?; - let rows = stmt.query(&[&email, - &access_token, - &login, - &name, - &avatar, - &id])?; - Ok(Model::from_row(&rows.iter().next().chain_error(|| { - internal("no user with email we just found") - })?)) + RETURNING *" + )?; + let rows = stmt.query(&[&email, &access_token, &login, &name, &avatar, &id])?; + Ok( + Model::from_row( + &rows.iter() + .next() + .chain_error(|| internal("no user with email we just found"))? + ) + ) } /// Converts this `User` model into an `EncodableUser` for JSON serialization. pub fn encodable(self) -> EncodableUser { - let User { id, email, name, gh_login, gh_avatar, .. } = self; + let User { + id, + email, + name, + gh_login, + gh_avatar, + .. + } = self; let url = format!("https://github.com/{}", gh_login); EncodableUser { id: id, @@ -186,7 +196,9 @@ impl Model for User { } } - fn table_name(_: Option) -> &'static str { "users" } + fn table_name(_: Option) -> &'static str { + "users" + } } /// Handles the `GET /authorize_url` route. @@ -207,13 +219,24 @@ impl Model for User { pub fn github_authorize(req: &mut Request) -> CargoResult { // Generate a random 16 char ASCII string let state: String = thread_rng().gen_ascii_chars().take(16).collect(); - req.session().insert("github_oauth_state".to_string(), state.clone()); + req.session() + .insert("github_oauth_state".to_string(), state.clone()); let url = req.app().github.authorize_url(state.clone()); #[derive(RustcEncodable)] - struct R { url: String, state: String } - Ok(req.json(&R { url: url.to_string(), state: state })) + struct R { + url: String, + state: String, + } + Ok( + req.json( + &R { + url: url.to_string(), + state: state, + } + ) + ) } /// Handles the `GET /authorize` route. @@ -256,7 +279,7 @@ pub fn github_access_token(req: &mut Request) -> CargoResult { let session_state = req.session().remove(&"github_oauth_state".to_string()); let session_state = session_state.as_ref().map(|a| &a[..]); if Some(&state[..]) != session_state { - return Err(human("invalid state parameter")) + return Err(human("invalid state parameter")); } } @@ -270,23 +293,25 @@ pub fn github_access_token(req: &mut Request) -> CargoResult { } // Fetch the access token from github using the code we just got - let token = req.app().github.exchange(code.clone()) + let token = req.app() + .github + .exchange(code.clone()) .map_err(|s| human(&s))?; let (handle, resp) = http::github(req.app(), "/user", &token)?; let ghuser: GithubUser = http::parse_github_response(handle, &resp)?; - let user = User::find_or_insert(req.tx()?, - ghuser.id, - &ghuser.login, - ghuser.email.as_ref() - .map(|s| &s[..]), - ghuser.name.as_ref() - .map(|s| &s[..]), - ghuser.avatar_url.as_ref() - .map(|s| &s[..]), - &token.access_token)?; - req.session().insert("user_id".to_string(), user.id.to_string()); + let user = User::find_or_insert( + req.tx()?, + ghuser.id, + &ghuser.login, + ghuser.email.as_ref().map(|s| &s[..]), + ghuser.name.as_ref().map(|s| &s[..]), + ghuser.avatar_url.as_ref().map(|s| &s[..]), + &token.access_token, + )?; + req.session() + .insert("user_id".to_string(), user.id.to_string()); req.mut_extensions().insert(user); me(req) } @@ -302,14 +327,20 @@ pub fn reset_token(req: &mut Request) -> CargoResult { let user = req.user()?; let conn = req.tx()?; - let rows = conn.query("UPDATE users SET api_token = DEFAULT \ - WHERE id = $1 RETURNING api_token", &[&user.id])?; - let token = rows.iter().next() + let rows = conn.query( + "UPDATE users SET api_token = DEFAULT \ + WHERE id = $1 RETURNING api_token", + &[&user.id], + )?; + let token = rows.iter() + .next() .map(|r| r.get("api_token")) .chain_error(|| NotFound)?; #[derive(RustcEncodable)] - struct R { api_token: String } + struct R { + api_token: String, + } Ok(req.json(&R { api_token: token })) } @@ -318,9 +349,19 @@ pub fn me(req: &mut Request) -> CargoResult { let user = req.user()?; #[derive(RustcEncodable)] - struct R { user: EncodableUser, api_token: String } + struct R { + user: EncodableUser, + api_token: String, + } let token = user.api_token.clone(); - Ok(req.json(&R{ user: user.clone().encodable(), api_token: token })) + Ok( + req.json( + &R { + user: user.clone().encodable(), + api_token: token, + } + ) + ) } /// Handles the `GET /users/:user_id` route. @@ -329,14 +370,13 @@ pub fn show(req: &mut Request) -> CargoResult { let name = &req.params()["user_id"]; let conn = req.db_conn()?; - let user = users.filter(gh_login.eq(name)) - .first::(&*conn)?; + let user = users.filter(gh_login.eq(name)).first::(&*conn)?; #[derive(RustcEncodable)] struct R { user: EncodableUser, } - Ok(req.json(&R{ user: user.encodable() })) + Ok(req.json(&R { user: user.encodable() })) } @@ -349,27 +389,23 @@ pub fn updates(req: &mut Request) -> CargoResult { let (offset, limit) = req.pagination(10, 100)?; let conn = req.db_conn()?; - let followed_crates = Follow::belonging_to(user) - .select(follows::crate_id); - let data = versions::table.inner_join(crates::table) + let followed_crates = Follow::belonging_to(user).select(follows::crate_id); + let data = versions::table + .inner_join(crates::table) .filter(crates::id.eq(any(followed_crates))) .order(versions::created_at.desc()) .limit(limit) .offset(offset) - .select(( - versions::all_columns, - crates::name, - sql::("COUNT(*) OVER ()"), - )) + .select((versions::all_columns, crates::name, sql::("COUNT(*) OVER ()"))) .load::<(Version, String, i64)>(&*conn)?; let more = data.get(0) .map(|&(_, _, count)| count > offset + limit) .unwrap_or(false); - let versions = data.into_iter().map(|(version, crate_name, _)| { - version.encodable(&crate_name) - }).collect(); + let versions = data.into_iter() + .map(|(version, crate_name, _)| version.encodable(&crate_name)) + .collect(); #[derive(RustcEncodable)] struct R { @@ -377,8 +413,17 @@ pub fn updates(req: &mut Request) -> CargoResult { meta: Meta, } #[derive(RustcEncodable)] - struct Meta { more: bool } - Ok(req.json(&R{ versions: versions, meta: Meta { more: more } })) + struct Meta { + more: bool, + } + Ok( + req.json( + &R { + versions: versions, + meta: Meta { more: more }, + } + ) + ) } #[cfg(test)] @@ -390,8 +435,7 @@ mod tests { fn connection() -> PgConnection { let _ = dotenv(); - let database_url = env::var("TEST_DATABASE_URL") - .expect("TEST_DATABASE_URL must be set to run tests"); + let database_url = env::var("TEST_DATABASE_URL").expect("TEST_DATABASE_URL must be set to run tests"); let conn = PgConnection::establish(&database_url).unwrap(); conn.begin_test_transaction().unwrap(); conn @@ -401,9 +445,11 @@ mod tests { fn new_users_have_different_api_tokens() { let conn = connection(); let user1 = NewUser::new(1, "foo", None, None, None, "foo") - .create_or_update(&conn).unwrap(); + .create_or_update(&conn) + .unwrap(); let user2 = NewUser::new(2, "bar", None, None, None, "bar") - .create_or_update(&conn).unwrap(); + .create_or_update(&conn) + .unwrap(); assert_ne!(user1.id, user2.id); assert_ne!(user1.api_token, user2.api_token); @@ -414,10 +460,12 @@ mod tests { fn updating_existing_user_doesnt_change_api_token() { let conn = connection(); let user_after_insert = NewUser::new(1, "foo", None, None, None, "foo") - .create_or_update(&conn).unwrap(); + .create_or_update(&conn) + .unwrap(); let original_token = user_after_insert.api_token; NewUser::new(1, "bar", None, None, None, "bar_token") - .create_or_update(&conn).unwrap(); + .create_or_update(&conn) + .unwrap(); let mut users = users::table.load::(&conn).unwrap(); assert_eq!(1, users.len()); let user = users.pop().unwrap(); diff --git a/src/util/errors.rs b/src/util/errors.rs index 6fa45c96d83..fcf2125f49d 100644 --- a/src/util/errors.rs +++ b/src/util/errors.rs @@ -3,30 +3,38 @@ use std::error::Error; use std::fmt; use conduit::Response; -use diesel::result::{Error as DieselError}; +use diesel::result::Error as DieselError; use util::json_response; -#[derive(RustcEncodable)] struct StringError { detail: String } -#[derive(RustcEncodable)] struct Bad { errors: Vec } +#[derive(RustcEncodable)] +struct StringError { + detail: String, +} +#[derive(RustcEncodable)] +struct Bad { + errors: Vec, +} // ============================================================================= // CargoError trait pub trait CargoError: Send + fmt::Display + 'static { fn description(&self) -> &str; - fn cause(&self) -> Option<&(CargoError)> { None } + fn cause(&self) -> Option<&(CargoError)> { + None + } fn response(&self) -> Option { if self.human() { - Some(json_response(&Bad { - errors: vec![StringError { detail: self.description().to_string() }] - })) + Some(json_response(&Bad { errors: vec![StringError { detail: self.description().to_string() }] })) } else { self.cause().and_then(|cause| cause.response()) } } - fn human(&self) -> bool { false } + fn human(&self) -> bool { + false + } } impl fmt::Debug for Box { @@ -36,16 +44,32 @@ impl fmt::Debug for Box { } impl CargoError for Box { - fn description(&self) -> &str { (**self).description() } - fn cause(&self) -> Option<&CargoError> { (**self).cause() } - fn human(&self) -> bool { (**self).human() } - fn response(&self) -> Option { (**self).response() } + fn description(&self) -> &str { + (**self).description() + } + fn cause(&self) -> Option<&CargoError> { + (**self).cause() + } + fn human(&self) -> bool { + (**self).human() + } + fn response(&self) -> Option { + (**self).response() + } } impl CargoError for Box { - fn description(&self) -> &str { (**self).description() } - fn cause(&self) -> Option<&CargoError> { (**self).cause() } - fn human(&self) -> bool { (**self).human() } - fn response(&self) -> Option { (**self).response() } + fn description(&self) -> &str { + (**self).description() + } + fn cause(&self) -> Option<&CargoError> { + (**self).cause() + } + fn human(&self) -> bool { + (**self).human() + } + fn response(&self) -> Option { + (**self).response() + } } pub type CargoResult = Result>; @@ -55,7 +79,9 @@ pub type CargoResult = Result>; pub trait ChainError { fn chain_error(self, callback: F) -> CargoResult - where E: CargoError, F: FnOnce() -> E; + where + E: CargoError, + F: FnOnce() -> E; } struct ChainedError { @@ -63,9 +89,15 @@ struct ChainedError { cause: Box, } -impl ChainError for F where F: FnOnce() -> CargoResult { +impl ChainError for F +where + F: FnOnce() -> CargoResult, +{ fn chain_error(self, callback: C) -> CargoResult - where E: CargoError, C: FnOnce() -> E { + where + E: CargoError, + C: FnOnce() -> E, + { self().chain_error(callback) } } @@ -73,19 +105,29 @@ impl ChainError for F where F: FnOnce() -> CargoResult { impl ChainError for Result { #[allow(trivial_casts)] fn chain_error(self, callback: C) -> CargoResult - where E2: CargoError, C: FnOnce() -> E2 { - self.map_err(move |err| { - Box::new(ChainedError { - error: callback(), - cause: Box::new(err), - }) as Box - }) + where + E2: CargoError, + C: FnOnce() -> E2, + { + self.map_err( + move |err| { + Box::new( + ChainedError { + error: callback(), + cause: Box::new(err), + } + ) as Box + } + ) } } impl ChainError for Option { fn chain_error(self, callback: C) -> CargoResult - where E: CargoError, C: FnOnce() -> E { + where + E: CargoError, + C: FnOnce() -> E, + { match self { Some(t) => Ok(t), None => Err(Box::new(callback())), @@ -94,10 +136,18 @@ impl ChainError for Option { } impl CargoError for ChainedError { - fn description(&self) -> &str { self.error.description() } - fn cause(&self) -> Option<&CargoError> { Some(&*self.cause) } - fn response(&self) -> Option { self.error.response() } - fn human(&self) -> bool { self.error.human() } + fn description(&self) -> &str { + self.error.description() + } + fn cause(&self) -> Option<&CargoError> { + Some(&*self.cause) + } + fn response(&self) -> Option { + self.error.response() + } + fn human(&self) -> bool { + self.error.human() + } } impl fmt::Display for ChainedError { @@ -119,7 +169,9 @@ impl From for Box { struct Shim(E); impl CargoError for Shim { - fn description(&self) -> &str { Error::description(&self.0) } + fn description(&self) -> &str { + Error::description(&self.0) + } } impl fmt::Display for Shim { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -131,10 +183,14 @@ impl From for Box { } impl CargoError for ::curl::Error { - fn description(&self) -> &str { Error::description(self) } + fn description(&self) -> &str { + Error::description(self) + } } impl CargoError for ::rustc_serialize::json::DecoderError { - fn description(&self) -> &str { Error::description(self) } + fn description(&self) -> &str { + Error::description(self) + } } // ============================================================================= @@ -158,20 +214,26 @@ impl fmt::Display for ConcreteCargoError { } impl CargoError for ConcreteCargoError { - fn description(&self) -> &str { &self.description } - fn cause(&self) -> Option<&CargoError> { self.cause.as_ref().map(|c| &**c) } - fn human(&self) -> bool { self.human } + fn description(&self) -> &str { + &self.description + } + fn cause(&self) -> Option<&CargoError> { + self.cause.as_ref().map(|c| &**c) + } + fn human(&self) -> bool { + self.human + } } pub struct NotFound; impl CargoError for NotFound { - fn description(&self) -> &str { "not found" } + fn description(&self) -> &str { + "not found" + } fn response(&self) -> Option { - let mut response = json_response(&Bad { - errors: vec![StringError { detail: "Not Found".to_string() }], - }); + let mut response = json_response(&Bad { errors: vec![StringError { detail: "Not Found".to_string() }] }); response.status = (404, "Not Found"); Some(response) } @@ -186,14 +248,18 @@ impl fmt::Display for NotFound { pub struct Unauthorized; impl CargoError for Unauthorized { - fn description(&self) -> &str { "unauthorized" } + fn description(&self) -> &str { + "unauthorized" + } fn response(&self) -> Option { - let mut response = json_response(&Bad { - errors: vec![StringError { + let mut response = json_response( + &Bad { + errors: vec![StringError { detail: "must be logged in to perform that action".to_string(), }], - }); + } + ); response.status = (403, "Forbidden"); Some(response) } @@ -206,37 +272,45 @@ impl fmt::Display for Unauthorized { } pub fn internal_error(error: &str, detail: &str) -> Box { - Box::new(ConcreteCargoError { - description: error.to_string(), - detail: Some(detail.to_string()), - cause: None, - human: false, - }) + Box::new( + ConcreteCargoError { + description: error.to_string(), + detail: Some(detail.to_string()), + cause: None, + human: false, + } + ) } pub fn internal(error: &S) -> Box { - Box::new(ConcreteCargoError { - description: error.to_string(), - detail: None, - cause: None, - human: false, - }) + Box::new( + ConcreteCargoError { + description: error.to_string(), + detail: None, + cause: None, + human: false, + } + ) } pub fn human(error: &S) -> Box { - Box::new(ConcreteCargoError { - description: error.to_string(), - detail: None, - cause: None, - human: true, - }) + Box::new( + ConcreteCargoError { + description: error.to_string(), + detail: None, + cause: None, + human: true, + } + ) } -pub fn std_error(e: Box) -> Box { +pub fn std_error(e: Box) -> Box { #[derive(Debug)] struct E(Box); impl Error for E { - fn description(&self) -> &str { self.0.description() } + fn description(&self) -> &str { + self.0.description() + } } impl fmt::Display for E { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/util/head.rs b/src/util/head.rs index 5f931ab0ee1..115feae3e5b 100644 --- a/src/util/head.rs +++ b/src/util/head.rs @@ -18,19 +18,25 @@ impl AroundMiddleware for Head { } impl Handler for Head { - fn call(&self, req: &mut Request) -> Result> { + fn call(&self, req: &mut Request) -> Result> { if req.method() == Method::Head { let mut req = RequestProxy { other: req, path: None, method: Some(Method::Get), }; - self.handler.as_ref().unwrap().call(&mut req).map(|r| { - Response { - body: Box::new(io::empty()), - ..r - } - }) + self.handler + .as_ref() + .unwrap() + .call(&mut req) + .map( + |r| { + Response { + body: Box::new(io::empty()), + ..r + } + } + ) } else { self.handler.as_ref().unwrap().call(req) } diff --git a/src/util/io_util.rs b/src/util/io_util.rs index 9ebc2308043..520431bea48 100644 --- a/src/util/io_util.rs +++ b/src/util/io_util.rs @@ -15,10 +15,7 @@ impl LimitErrorReader { impl Read for LimitErrorReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { match self.inner.read(buf) { - Ok(0) if self.inner.limit() == 0 => { - Err(io::Error::new(io::ErrorKind::Other, - "maximum limit reached when reading")) - } + Ok(0) if self.inner.limit() == 0 => Err(io::Error::new(io::ErrorKind::Other, "maximum limit reached when reading")), e => e, } } @@ -27,19 +24,14 @@ impl Read for LimitErrorReader { pub fn read_le_u32(r: &mut R) -> io::Result { let mut b = [0; 4]; read_fill(r, &mut b)?; - Ok( (b[0] as u32) | - ((b[1] as u32) << 8) | - ((b[2] as u32) << 16) | - ((b[3] as u32) << 24)) + Ok((b[0] as u32) | ((b[1] as u32) << 8) | ((b[2] as u32) << 16) | ((b[3] as u32) << 24)) } -pub fn read_fill(r: &mut R, mut slice: &mut [u8]) - -> io::Result<()> { +pub fn read_fill(r: &mut R, mut slice: &mut [u8]) -> io::Result<()> { while !slice.is_empty() { let n = r.read(slice)?; if n == 0 { - return Err(io::Error::new(io::ErrorKind::Other, - "end of file reached")) + return Err(io::Error::new(io::ErrorKind::Other, "end of file reached")); } slice = &mut mem::replace(&mut slice, &mut [])[n..]; } diff --git a/src/util/lazy_cell.rs b/src/util/lazy_cell.rs index 9ab36f7430f..e530473d597 100644 --- a/src/util/lazy_cell.rs +++ b/src/util/lazy_cell.rs @@ -33,7 +33,9 @@ impl LazyCell { } /// Test whether this cell has been previously filled. - pub fn filled(&self) -> bool { self.inner.borrow().is_some() } + pub fn filled(&self) -> bool { + self.inner.borrow().is_some() + } /// Borrows the contents of this lazy cell for the duration of the cell /// itself. @@ -43,7 +45,7 @@ impl LazyCell { pub fn borrow(&self) -> Option<&T> { match *self.inner.borrow() { Some(ref inner) => unsafe { Some(mem::transmute(inner)) }, - None => None + None => None, } } diff --git a/src/util/mod.rs b/src/util/mod.rs index 866d1256111..fb197be25b7 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -14,7 +14,7 @@ use self::errors::NotFound; pub use self::errors::{CargoError, CargoResult, internal, human, internal_error}; pub use self::errors::{ChainError, std_error}; -pub use self::hasher::{HashingReader}; +pub use self::hasher::HashingReader; pub use self::head::Head; pub use self::io_util::{LimitErrorReader, read_le_u32, read_fill}; pub use self::lazy_cell::LazyCell; @@ -40,30 +40,33 @@ pub fn json_response(t: &T) -> Response { let s = json::encode(t).unwrap(); let json = fixup(s.parse().unwrap()).to_string(); let mut headers = HashMap::new(); - headers.insert("Content-Type".to_string(), - vec!["application/json; charset=utf-8".to_string()]); + headers.insert( + "Content-Type".to_string(), + vec!["application/json; charset=utf-8".to_string()], + ); headers.insert("Content-Length".to_string(), vec![json.len().to_string()]); return Response { - status: (200, "OK"), - headers: headers, - body: Box::new(Cursor::new(json.into_bytes())), - }; + status: (200, "OK"), + headers: headers, + body: Box::new(Cursor::new(json.into_bytes())), + }; fn fixup(json: Json) -> Json { match json { Json::Object(object) => { - Json::Object(object.into_iter().map(|(k, v)| { - let k = if k == "krate" { - "crate".to_string() - } else { - k - }; - (k, fixup(v)) - }).collect()) - } - Json::Array(list) => { - Json::Array(list.into_iter().map(fixup).collect()) + Json::Object( + object + .into_iter() + .map( + |(k, v)| { + let k = if k == "krate" { "crate".to_string() } else { k }; + (k, fixup(v)) + } + ) + .collect() + ) } + Json::Array(list) => Json::Array(list.into_iter().map(fixup).collect()), j => j, } } @@ -76,8 +79,7 @@ impl<'a> RequestUtils for Request + 'a { } fn query(&self) -> HashMap { - url::form_urlencoded::parse(self.query_string().unwrap_or("") - .as_bytes()) + url::form_urlencoded::parse(self.query_string().unwrap_or("").as_bytes()) .map(|(a, b)| (a.into_owned(), b.into_owned())) .collect() } @@ -93,22 +95,27 @@ impl<'a> RequestUtils for Request + 'a { } fn wants_json(&self) -> bool { - self.headers().find("Accept").map(|accept| { - accept.iter().any(|s| s.contains("json")) - }).unwrap_or(false) + self.headers() + .find("Accept") + .map(|accept| accept.iter().any(|s| s.contains("json"))) + .unwrap_or(false) } fn pagination(&self, default: usize, max: usize) -> CargoResult<(i64, i64)> { let query = self.query(); - let page = query.get("page").and_then(|s| s.parse::().ok()) - .unwrap_or(1); - let limit = query.get("per_page").and_then(|s| s.parse::().ok()) - .unwrap_or(default); + let page = query + .get("page") + .and_then(|s| s.parse::().ok()) + .unwrap_or(1); + let limit = query + .get("per_page") + .and_then(|s| s.parse::().ok()) + .unwrap_or(default); if limit > max { - return Err(human(&format_args!("cannot request more than {} items", max))) + return Err(human(&format_args!("cannot request more than {} items", max))); } if page == 0 { - return Err(human("page indexing starts from 1, page 0 is invalid")) + return Err(human("page indexing starts from 1, page 0 is invalid")); } Ok((((page - 1) * limit) as i64, limit as i64)) } @@ -117,7 +124,7 @@ impl<'a> RequestUtils for Request + 'a { pub struct C(pub fn(&mut Request) -> CargoResult); impl Handler for C { - fn call(&self, req: &mut Request) -> Result> { + fn call(&self, req: &mut Request) -> Result> { let C(f) = *self; match f(req) { Ok(resp) => { @@ -127,7 +134,7 @@ impl Handler for C { Err(e) => { match e.response() { Some(response) => Ok(response), - None => Err(std_error(e)) + None => Err(std_error(e)), } } } @@ -137,21 +144,23 @@ impl Handler for C { pub struct R(pub Arc); impl Handler for R { - fn call(&self, req: &mut Request) -> Result> { + fn call(&self, req: &mut Request) -> Result> { let path = req.params()["path"].to_string(); let R(ref sub_router) = *self; - sub_router.call(&mut RequestProxy { - other: req, - path: Some(&path), - method: None, - }) + sub_router.call( + &mut RequestProxy { + other: req, + path: Some(&path), + method: None, + } + ) } } pub struct R404(pub RouteBuilder); impl Handler for R404 { - fn call(&self, req: &mut Request) -> Result> { + fn call(&self, req: &mut Request) -> Result> { let R404(ref router) = *self; match router.recognize(&req.method(), req.path()) { Ok(m) => { diff --git a/src/util/request_proxy.rs b/src/util/request_proxy.rs index e29063abdd0..8c1929db133 100644 --- a/src/util/request_proxy.rs +++ b/src/util/request_proxy.rs @@ -19,10 +19,16 @@ impl<'a> Request for RequestProxy<'a> { self.other.conduit_version() } fn method(&self) -> conduit::Method { - self.method.clone().unwrap_or_else(|| self.other.method().clone()) + self.method + .clone() + .unwrap_or_else(|| self.other.method().clone()) + } + fn scheme(&self) -> conduit::Scheme { + self.other.scheme() + } + fn host(&self) -> conduit::Host { + self.other.host() } - fn scheme(&self) -> conduit::Scheme { self.other.scheme() } - fn host(&self) -> conduit::Host { self.other.host() } fn virtual_root(&self) -> Option<&str> { self.other.virtual_root() } @@ -32,14 +38,18 @@ impl<'a> Request for RequestProxy<'a> { fn query_string(&self) -> Option<&str> { self.other.query_string() } - fn remote_addr(&self) -> SocketAddr { self.other.remote_addr() } + fn remote_addr(&self) -> SocketAddr { + self.other.remote_addr() + } fn content_length(&self) -> Option { self.other.content_length() } fn headers(&self) -> &conduit::Headers { self.other.headers() } - fn body(&mut self) -> &mut Read { self.other.body() } + fn body(&mut self) -> &mut Read { + self.other.body() + } fn extensions(&self) -> &conduit::Extensions { self.other.extensions() } diff --git a/src/version.rs b/src/version.rs index 218d9b36b4b..38d51c205da 100644 --- a/src/version.rs +++ b/src/version.rs @@ -46,7 +46,7 @@ pub struct NewVersion { } pub struct Author { - pub name: String + pub name: String, } #[derive(RustcEncodable, RustcDecodable)] @@ -71,33 +71,37 @@ pub struct VersionLinks { } impl Version { - pub fn find_by_num(conn: &GenericConnection, - crate_id: i32, - num: &semver::Version) - -> CargoResult> { + pub fn find_by_num(conn: &GenericConnection, crate_id: i32, num: &semver::Version) -> CargoResult> { let num = num.to_string(); - let stmt = conn.prepare("SELECT * FROM versions \ - WHERE crate_id = $1 AND num = $2")?; + let stmt = conn.prepare( + "SELECT * FROM versions \ + WHERE crate_id = $1 AND num = $2" + )?; let rows = stmt.query(&[&crate_id, &num])?; Ok(rows.iter().next().map(|r| Model::from_row(&r))) } - pub fn insert(conn: &GenericConnection, - crate_id: i32, - num: &semver::Version, - features: &HashMap>, - authors: &[String]) - -> CargoResult { + pub fn insert( + conn: &GenericConnection, + crate_id: i32, + num: &semver::Version, + features: &HashMap>, + authors: &[String], + ) -> CargoResult { let num = num.to_string(); let features = json::encode(features).unwrap(); - let stmt = conn.prepare("INSERT INTO versions \ + let stmt = conn.prepare( + "INSERT INTO versions \ (crate_id, num, features) \ VALUES ($1, $2, $3) \ - RETURNING *")?; + RETURNING *" + )?; let rows = stmt.query(&[&crate_id, &num, &features])?; - let ret: Version = Model::from_row(&rows.iter().next().chain_error(|| { - internal("no version returned") - })?); + let ret: Version = Model::from_row( + &rows.iter() + .next() + .chain_error(|| internal("no version returned"))? + ); for author in authors { ret.add_author(conn, author)?; } @@ -109,8 +113,16 @@ impl Version { } pub fn encodable(self, crate_name: &str) -> EncodableVersion { - let Version { id, num, updated_at, created_at, - downloads, features, yanked, .. } = self; + let Version { + id, + num, + updated_at, + created_at, + downloads, + features, + yanked, + .. + } = self; let num = num.to_string(); EncodableVersion { dl_path: format!("/api/v1/crates/{}/{}/download", crate_name, num), @@ -133,8 +145,7 @@ impl Version { } /// Returns (dependency, crate dependency name) - pub fn dependencies(&self, conn: &PgConnection) - -> QueryResult> { + pub fn dependencies(&self, conn: &PgConnection) -> QueryResult> { Dependency::belonging_to(self) .inner_join(crates::table) .select((dependencies::all_columns, crates::name)) @@ -143,56 +154,67 @@ impl Version { } pub fn authors(&self, conn: &GenericConnection) -> CargoResult> { - let stmt = conn.prepare("SELECT * FROM version_authors + let stmt = conn.prepare( + "SELECT * FROM version_authors WHERE version_id = $1 - ORDER BY name ASC")?; + ORDER BY name ASC" + )?; let rows = stmt.query(&[&self.id])?; - Ok(rows.into_iter().map(|row| { - Author { name: row.get("name") } - }).collect()) + Ok( + rows.into_iter() + .map(|row| Author { name: row.get("name") }) + .collect() + ) } - pub fn add_author(&self, - conn: &GenericConnection, - name: &str) -> CargoResult<()> { - conn.execute("INSERT INTO version_authors (version_id, name) - VALUES ($1, $2)", &[&self.id, &name])?; + pub fn add_author(&self, conn: &GenericConnection, name: &str) -> CargoResult<()> { + conn.execute( + "INSERT INTO version_authors (version_id, name) + VALUES ($1, $2)", + &[&self.id, &name], + )?; Ok(()) } pub fn yank(&self, conn: &GenericConnection, yanked: bool) -> CargoResult<()> { - conn.execute("UPDATE versions SET yanked = $1 WHERE id = $2", - &[&yanked, &self.id])?; + conn.execute( + "UPDATE versions SET yanked = $1 WHERE id = $2", + &[&yanked, &self.id], + )?; Ok(()) } - pub fn max(versions: T) -> semver::Version where - T: IntoIterator, + pub fn max(versions: T) -> semver::Version + where + T: IntoIterator, { - versions.into_iter() + versions + .into_iter() .max() - .unwrap_or_else(|| semver::Version { - major: 0, - minor: 0, - patch: 0, - pre: vec![], - build: vec![], - }) + .unwrap_or_else( + || { + semver::Version { + major: 0, + minor: 0, + patch: 0, + pre: vec![], + build: vec![], + } + } + ) } } impl NewVersion { - pub fn new( - crate_id: i32, - num: &semver::Version, - features: &HashMap>, - ) -> CargoResult { + pub fn new(crate_id: i32, num: &semver::Version, features: &HashMap>) -> CargoResult { let features = json::encode(features)?; - Ok(NewVersion { - crate_id: crate_id, - num: num.to_string(), - features: features, - }) + Ok( + NewVersion { + crate_id: crate_id, + num: num.to_string(), + features: features, + } + ) } pub fn save(&self, conn: &PgConnection, authors: &[String]) -> CargoResult { @@ -200,26 +222,40 @@ impl NewVersion { use diesel::expression::dsl::exists; use schema::versions::dsl::*; - let already_uploaded = versions.filter(crate_id.eq(self.crate_id)) + let already_uploaded = versions + .filter(crate_id.eq(self.crate_id)) .filter(num.eq(&self.num)); if select(exists(already_uploaded)).get_result(conn)? { - return Err(human(&format_args!("crate version `{}` is already \ - uploaded", self.num))); + return Err( + human( + &format_args!("crate version `{}` is already \ + uploaded", self.num) + ) + ); } - conn.transaction(|| { - let version = insert(self).into(versions) - .get_result::(conn)?; - - let new_authors = authors.iter().map(|s| NewAuthor { - version_id: version.id, - name: &*s, - }).collect::>(); - - insert(&new_authors).into(version_authors::table) - .execute(conn)?; - Ok(version) - }) + conn.transaction( + || { + let version = insert(self).into(versions).get_result::(conn)?; + + let new_authors = authors + .iter() + .map( + |s| { + NewAuthor { + version_id: version.id, + name: &*s, + } + } + ) + .collect::>(); + + insert(&new_authors) + .into(version_authors::table) + .execute(conn)?; + Ok(version) + } + ) } } @@ -234,9 +270,9 @@ impl Queryable for Version { type Row = (i32, i32, String, Timespec, Timespec, i32, Option, bool); fn build(row: Self::Row) -> Self { - let features = row.6.map(|s| { - json::decode(&s).unwrap() - }).unwrap_or_else(HashMap::new); + let features = row.6 + .map(|s| json::decode(&s).unwrap()) + .unwrap_or_else(HashMap::new); Version { id: row.0, crate_id: row.1, @@ -254,9 +290,9 @@ impl Model for Version { fn from_row(row: &Row) -> Version { let num: String = row.get("num"); let features: Option = row.get("features"); - let features = features.map(|s| { - json::decode(&s).unwrap() - }).unwrap_or_else(HashMap::new); + let features = features + .map(|s| json::decode(&s).unwrap()) + .unwrap_or_else(HashMap::new); Version { id: row.get("id"), crate_id: row.get("crate_id"), @@ -268,7 +304,9 @@ impl Model for Version { yanked: row.get("yanked"), } } - fn table_name(_: Option) -> &'static str { "versions" } + fn table_name(_: Option) -> &'static str { + "versions" + } } /// Handles the `GET /versions` route. @@ -277,27 +315,24 @@ pub fn index(req: &mut Request) -> CargoResult { let conn = req.tx()?; // Extract all ids requested. - let query = url::form_urlencoded::parse(req.query_string().unwrap_or("") - .as_bytes()); - let ids = query.filter_map(|(ref a, ref b)| { - if *a == "ids[]" { - b.parse().ok() - } else { - None - } - }).collect::>(); + let query = url::form_urlencoded::parse(req.query_string().unwrap_or("").as_bytes()); + let ids = query + .filter_map(|(ref a, ref b)| if *a == "ids[]" { b.parse().ok() } else { None }) + .collect::>(); // Load all versions // // TODO: can rust-postgres do this for us? let mut versions = Vec::new(); if !ids.is_empty() { - let stmt = conn.prepare("\ + let stmt = conn.prepare( + "\ SELECT versions.*, crates.name AS crate_name FROM versions LEFT JOIN crates ON crates.id = versions.crate_id WHERE versions.id = ANY($1) - ")?; + " + )?; for row in stmt.query(&[&ids])?.iter() { let v: Version = Model::from_row(&row); let crate_name: String = row.get("crate_name"); @@ -306,7 +341,9 @@ pub fn index(req: &mut Request) -> CargoResult { } #[derive(RustcEncodable)] - struct R { versions: Vec } + struct R { + versions: Vec, + } Ok(req.json(&R { versions: versions })) } @@ -318,7 +355,8 @@ pub fn show(req: &mut Request) -> CargoResult { let id = &req.params()["version_id"]; let id = id.parse().unwrap_or(0); let conn = req.db_conn()?; - versions::table.find(id) + versions::table + .find(id) .inner_join(crates::table) .select((versions::all_columns, ::krate::ALL_COLUMNS)) .first(&*conn)? @@ -326,23 +364,29 @@ pub fn show(req: &mut Request) -> CargoResult { }; #[derive(RustcEncodable)] - struct R { version: EncodableVersion } + struct R { + version: EncodableVersion, + } Ok(req.json(&R { version: version.encodable(&krate.name) })) } fn version_and_crate_old(req: &mut Request) -> CargoResult<(Version, Crate)> { let crate_name = &req.params()["crate_id"]; let semver = &req.params()["version"]; - let semver = semver::Version::parse(semver).map_err(|_| { - human(&format_args!("invalid semver: {}", semver)) - })?; + let semver = semver::Version::parse(semver) + .map_err(|_| human(&format_args!("invalid semver: {}", semver)))?; let tx = req.tx()?; let krate = Crate::find_by_name(tx, crate_name)?; let version = Version::find_by_num(tx, krate.id, &semver)?; - let version = version.chain_error(|| { - human(&format_args!("crate `{}` does not have a version `{}`", - crate_name, semver)) - })?; + let version = version + .chain_error( + || { + human( + &format_args!("crate `{}` does not have a version `{}`", + crate_name, semver) + ) + } + )?; Ok((version, krate)) } @@ -357,10 +401,14 @@ fn version_and_crate(req: &mut Request) -> CargoResult<(Version, Crate)> { let version = Version::belonging_to(&krate) .filter(versions::num.eq(semver)) .first(&*conn) - .map_err(|_| { - human(&format_args!("crate `{}` does not have a version `{}`", - crate_name, semver)) - })?; + .map_err( + |_| { + human( + &format_args!("crate `{}` does not have a version `{}`", + crate_name, semver) + ) + } + )?; Ok((version, krate)) } @@ -369,13 +417,15 @@ pub fn dependencies(req: &mut Request) -> CargoResult { let (version, _) = version_and_crate(req)?; let conn = req.db_conn()?; let deps = version.dependencies(&*conn)?; - let deps = deps.into_iter().map(|(dep, crate_name)| { - dep.encodable(&crate_name, None) - }).collect(); + let deps = deps.into_iter() + .map(|(dep, crate_name)| dep.encodable(&crate_name, None)) + .collect(); #[derive(RustcEncodable)] - struct R { dependencies: Vec } - Ok(req.json(&R{ dependencies: deps })) + struct R { + dependencies: Vec, + } + Ok(req.json(&R { dependencies: deps })) } /// Handles the `GET /crates/:crate_id/:version/downloads` route. @@ -383,9 +433,11 @@ pub fn downloads(req: &mut Request) -> CargoResult { use diesel::expression::dsl::date; let (version, _) = version_and_crate(req)?; let conn = req.db_conn()?; - let cutoff_end_date = req.query().get("before_date") + let cutoff_end_date = req.query() + .get("before_date") .and_then(|d| strptime(d, "%Y-%m-%d").ok()) - .unwrap_or_else(now_utc).to_timespec(); + .unwrap_or_else(now_utc) + .to_timespec(); let cutoff_start_date = cutoff_end_date + Duration::days(-89); let downloads = VersionDownload::belonging_to(&version) @@ -397,8 +449,10 @@ pub fn downloads(req: &mut Request) -> CargoResult { .collect(); #[derive(RustcEncodable)] - struct R { version_downloads: Vec } - Ok(req.json(&R{ version_downloads: downloads })) + struct R { + version_downloads: Vec, + } + Ok(req.json(&R { version_downloads: downloads })) } /// Handles the `GET /crates/:crate_id/:version/authors` route. @@ -411,10 +465,22 @@ pub fn authors(req: &mut Request) -> CargoResult { // This was never implemented. This complicated return struct // is all that is left, hear for backwards compatibility. #[derive(RustcEncodable)] - struct R { users: Vec<::user::EncodableUser>, meta: Meta } + struct R { + users: Vec<::user::EncodableUser>, + meta: Meta, + } #[derive(RustcEncodable)] - struct Meta { names: Vec } - Ok(req.json(&R{ users: vec![], meta: Meta { names: names } })) + struct Meta { + names: Vec, + } + Ok( + req.json( + &R { + users: vec![], + meta: Meta { names: names }, + } + ) + ) } /// Handles the `DELETE /crates/:crate_id/:version/yank` route. @@ -433,19 +499,24 @@ fn modify_yank(req: &mut Request, yanked: bool) -> CargoResult { let conn = req.db_conn()?; let owners = krate.owners(&conn)?; if rights(req.app(), &owners, user)? < Rights::Publish { - return Err(human("must already be an owner to yank or unyank")) + return Err(human("must already be an owner to yank or unyank")); } if version.yanked != yanked { - conn.transaction::<_, Box, _>(|| { - diesel::update(&version).set(versions::yanked.eq(yanked)) - .execute(&*conn)?; - git::yank(&**req.app(), &krate.name, &version.num, yanked)?; - Ok(()) - })?; + conn.transaction::<_, Box, _>( + || { + diesel::update(&version) + .set(versions::yanked.eq(yanked)) + .execute(&*conn)?; + git::yank(&**req.app(), &krate.name, &version.num, yanked)?; + Ok(()) + } + )?; } #[derive(RustcEncodable)] - struct R { ok: bool } - Ok(req.json(&R{ ok: true })) + struct R { + ok: bool, + } + Ok(req.json(&R { ok: true })) } From de22786f5c9335bee6ca54f3447749fa36abc43c Mon Sep 17 00:00:00 2001 From: Vignesh Date: Tue, 13 Jun 2017 14:36:22 +1000 Subject: [PATCH 05/14] Added rustfmt check --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 5c2bfe1e026..246a617d971 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,7 @@ install: - yarn - yarn run bower install - cargo install diesel_cli --debug --no-default-features --features postgres && export PATH=$HOME/.cargo/bin:$PATH + - which rustfmt || cargo install rustfmt before_script: - diesel database setup @@ -36,6 +37,7 @@ matrix: include: - rust: stable script: + - cargo fmt -- --write-mode=diff - cargo build - cargo test - yarn run test From 0a4ed48ef1fb700a27251d7d509c529de4a61296 Mon Sep 17 00:00:00 2001 From: Vignesh Date: Tue, 13 Jun 2017 14:49:44 +1000 Subject: [PATCH 06/14] Added rustfmt instructions --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1fe03282c3c..9f21f26dee0 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,11 @@ A volunteer will get back to you as soon as possible. Welcome! We love contributions! Crates.io is an [Ember](https://emberjs.com/) frontend with a Rust backend, and there are many tasks appropriate for a -variety of skill levels. +variety of skill levels. + +The Rust backend uses rustfmt for code formatting, so ensure that you run it prior +to submitting a pull request. More information on setting up and running rustfmt can +be found [here](https://github.com/rust-lang-nursery/rustfmt/blob/master/README.md). Please see [docs/CONTRIBUTING.md](https://github.com/rust-lang/crates.io/blob/master/docs/CONTRIBUTING.md) for ideas about what to work on and how to set up a development environment. From 116e1bdd3a02e3407f57fba7a0cb78aacd6f6dc5 Mon Sep 17 00:00:00 2001 From: Vignesh Date: Tue, 13 Jun 2017 23:18:55 +1000 Subject: [PATCH 07/14] Output rustfmt version --- .rustfmt.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.rustfmt.toml b/.rustfmt.toml index dabeeeccb52..e640536fa2a 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -6,4 +6,4 @@ generics_indent = "Block" fn_call_style = "Block" combine_control_expr = true fn_args_paren_newline = false -max_width = 140 \ No newline at end of file +max_width = 160 From 2038e2a0a78290b5ca4ee99a26864106a3d798a0 Mon Sep 17 00:00:00 2001 From: Vignesh Date: Tue, 13 Jun 2017 23:19:06 +1000 Subject: [PATCH 08/14] cargo fmt --- .travis.yml | 3 +- src/badge.rs | 34 +- src/bin/delete-crate.rs | 49 +-- src/bin/delete-version.rs | 14 +- src/bin/fill-in-user-id.rs | 22 +- src/bin/populate.rs | 12 +- src/bin/transfer-crates.rs | 14 +- src/bin/update-downloads.rs | 179 ++++---- src/categories.rs | 46 +- src/category.rs | 231 +++++------ src/db.rs | 19 +- src/dependency.rs | 110 ++--- src/dist.rs | 13 +- src/download.rs | 2 +- src/git.rs | 133 +++--- src/http.rs | 38 +- src/keyword.rs | 62 ++- src/krate.rs | 808 ++++++++++++++++++------------------ src/lib.rs | 25 +- src/model.rs | 6 +- src/owner.rs | 93 ++--- src/tests/all.rs | 106 +++-- src/tests/badge.rs | 6 +- src/tests/category.rs | 9 +- src/tests/git.rs | 13 +- src/tests/krate.rs | 307 ++++++-------- src/tests/record.rs | 157 ++++--- src/tests/team.rs | 48 +-- src/tests/user.rs | 18 +- src/upload.rs | 33 +- src/uploaders.rs | 86 ++-- src/user/middleware.rs | 6 +- src/user/mod.rs | 127 +++--- src/util/errors.rs | 78 ++-- src/util/hasher.rs | 3 +- src/util/head.rs | 18 +- src/util/io_util.rs | 9 +- src/util/mod.rs | 36 +- src/util/request_proxy.rs | 6 +- src/version.rs | 235 +++++------ 40 files changed, 1525 insertions(+), 1689 deletions(-) diff --git a/.travis.yml b/.travis.yml index 246a617d971..2c47e57ecdb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,8 @@ install: - yarn - yarn run bower install - cargo install diesel_cli --debug --no-default-features --features postgres && export PATH=$HOME/.cargo/bin:$PATH - - which rustfmt || cargo install rustfmt + - cargo install rustfmt + - rustfmt --version before_script: - diesel database setup diff --git a/src/badge.rs b/src/badge.rs index e7089f48d63..7e885800608 100644 --- a/src/badge.rs +++ b/src/badge.rs @@ -76,15 +76,11 @@ impl Badge { } } - pub fn update_crate<'a>( - conn: &PgConnection, - krate: &Crate, - badges: Option<&'a HashMap>>, - ) -> CargoResult> { + pub fn update_crate<'a>(conn: &PgConnection, krate: &Crate, badges: Option<&'a HashMap>>) -> CargoResult> { use diesel::{insert, delete}; #[derive(Insertable)] - #[table_name="badges"] + #[table_name = "badges"] struct NewBadge<'a> { crate_id: i32, badge_type: &'a str, @@ -100,26 +96,22 @@ impl Badge { let json = json!({"badge_type": k, "attributes": attributes_json}); if serde_json::from_value::(json).is_ok() { - new_badges.push( - NewBadge { - crate_id: krate.id, - badge_type: &**k, - attributes: attributes_json, - } - ); + new_badges.push(NewBadge { + crate_id: krate.id, + badge_type: &**k, + attributes: attributes_json, + }); } else { invalid_badges.push(&**k); } } } - conn.transaction( - || { - delete(badges::table.filter(badges::crate_id.eq(krate.id))) - .execute(conn)?; - insert(&new_badges).into(badges::table).execute(conn)?; - Ok(invalid_badges) - } - ) + conn.transaction(|| { + delete(badges::table.filter(badges::crate_id.eq(krate.id))) + .execute(conn)?; + insert(&new_badges).into(badges::table).execute(conn)?; + Ok(invalid_badges) + }) } } diff --git a/src/bin/delete-crate.rs b/src/bin/delete-crate.rs index 00887fccc5d..3e32cec3115 100644 --- a/src/bin/delete-crate.rs +++ b/src/bin/delete-crate.rs @@ -55,16 +55,14 @@ fn delete(tx: &postgres::transaction::Transaction) { for v in versions.iter() { println!("deleting version {} ({})", v.num, v.id); let n = tx.execute( - "DELETE FROM version_downloads WHERE version_id = $1", - &[&v.id], - ) - .unwrap(); + "DELETE FROM version_downloads WHERE version_id = $1", + &[&v.id], + ).unwrap(); println!(" {} download records deleted", n); let n = tx.execute( - "DELETE FROM version_authors WHERE version_id = $1", - &[&v.id], - ) - .unwrap(); + "DELETE FROM version_authors WHERE version_id = $1", + &[&v.id], + ).unwrap(); println!(" {} author records deleted", n); let n = tx.execute("DELETE FROM dependencies WHERE version_id = $1", &[&v.id]) .unwrap(); @@ -80,10 +78,9 @@ fn delete(tx: &postgres::transaction::Transaction) { println!("deleting crate download records"); let n = tx.execute( - "DELETE FROM crate_downloads WHERE crate_id = $1", - &[&krate.id], - ) - .unwrap(); + "DELETE FROM crate_downloads WHERE crate_id = $1", + &[&krate.id], + ).unwrap(); println!(" {} deleted", n); println!("deleting crate owners"); @@ -93,33 +90,29 @@ fn delete(tx: &postgres::transaction::Transaction) { println!("disabling reserved crate name trigger"); let _ = tx.execute( - "ALTER TABLE crates DISABLE TRIGGER trigger_ensure_crate_name_not_reserved;", - &[], - ) - .unwrap(); + "ALTER TABLE crates DISABLE TRIGGER trigger_ensure_crate_name_not_reserved;", + &[], + ).unwrap(); println!("deleting crate keyword connections"); let n = tx.execute( - "DELETE FROM crates_keywords WHERE crate_id = $1", - &[&krate.id], - ) - .unwrap(); + "DELETE FROM crates_keywords WHERE crate_id = $1", + &[&krate.id], + ).unwrap(); println!(" {} deleted", n); println!("deleting crate category connections"); let n = tx.execute( - "DELETE FROM crates_categories WHERE crate_id = $1", - &[&krate.id], - ) - .unwrap(); + "DELETE FROM crates_categories WHERE crate_id = $1", + &[&krate.id], + ).unwrap(); println!(" {} deleted", n); println!("enabling reserved crate name trigger"); let _ = tx.execute( - "ALTER TABLE crates ENABLE TRIGGER trigger_ensure_crate_name_not_reserved;", - &[], - ) - .unwrap(); + "ALTER TABLE crates ENABLE TRIGGER trigger_ensure_crate_name_not_reserved;", + &[], + ).unwrap(); println!("deleting crate badges"); let n = tx.execute("DELETE FROM badges WHERE crate_id = $1", &[&krate.id]) diff --git a/src/bin/delete-version.rs b/src/bin/delete-version.rs index 826cdc968d9..9679323d59c 100644 --- a/src/bin/delete-version.rs +++ b/src/bin/delete-version.rs @@ -65,16 +65,14 @@ fn delete(tx: &postgres::transaction::Transaction) { println!("deleting version {} ({})", v.num, v.id); let n = tx.execute( - "DELETE FROM version_downloads WHERE version_id = $1", - &[&v.id], - ) - .unwrap(); + "DELETE FROM version_downloads WHERE version_id = $1", + &[&v.id], + ).unwrap(); println!(" {} download records deleted", n); let n = tx.execute( - "DELETE FROM version_authors WHERE version_id = $1", - &[&v.id], - ) - .unwrap(); + "DELETE FROM version_authors WHERE version_id = $1", + &[&v.id], + ).unwrap(); println!(" {} author records deleted", n); let n = tx.execute("DELETE FROM dependencies WHERE version_id = $1", &[&v.id]) .unwrap(); diff --git a/src/bin/fill-in-user-id.rs b/src/bin/fill-in-user-id.rs index 0e3a9dea724..d3a907a2ca1 100644 --- a/src/bin/fill-in-user-id.rs +++ b/src/bin/fill-in-user-id.rs @@ -56,15 +56,13 @@ fn update(app: &App, tx: &postgres::transaction::Transaction) { let rows = tx.query(query, &[]) .unwrap() .into_iter() - .map( - |row| { - let id: i32 = row.get("id"); - let login: String = row.get("gh_login"); - let token: String = row.get("gh_access_token"); - let avatar: Option = row.get("gh_avatar"); - (id, login, http::token(token), avatar) - } - ) + .map(|row| { + let id: i32 = row.get("id"); + let login: String = row.get("gh_login"); + let token: String = row.get("gh_access_token"); + let avatar: Option = row.get("gh_avatar"); + (id, login, http::token(token), avatar) + }) .collect::>(); for (id, login, token, avatar) in rows { @@ -80,9 +78,9 @@ fn update(app: &App, tx: &postgres::transaction::Transaction) { } if ghuser.login == login { tx.execute( - "UPDATE users SET gh_id = $1 WHERE id = $2", - &[&ghuser.id, &id], - )?; + "UPDATE users SET gh_id = $1 WHERE id = $2", + &[&ghuser.id, &id], + )?; Ok(()) } else { Err(human(&format_args!("different login: {}", ghuser.login))) diff --git a/src/bin/populate.rs b/src/bin/populate.rs index 84fe9a31d4e..8dfa0514f6f 100644 --- a/src/bin/populate.rs +++ b/src/bin/populate.rs @@ -27,9 +27,9 @@ fn main() { } fn update(tx: &postgres::transaction::Transaction) -> postgres::Result<()> { - let ids = env::args() - .skip(1) - .filter_map(|arg| arg.parse::().ok()); + let ids = env::args().skip(1).filter_map( + |arg| arg.parse::().ok(), + ); for id in ids { let now = time::now_utc().to_timespec(); let mut rng = StdRng::new().unwrap(); @@ -39,11 +39,11 @@ fn update(tx: &postgres::transaction::Transaction) -> postgres::Result<()> { let moment = now + Duration::days(-day); dls += rng.gen_range(-100, 100); tx.execute( - "INSERT INTO version_downloads \ + "INSERT INTO version_downloads \ (version_id, downloads, date) \ VALUES ($1, $2, $3)", - &[&id, &dls, &moment], - )?; + &[&id, &dls, &moment], + )?; } } Ok(()) diff --git a/src/bin/transfer-crates.rs b/src/bin/transfer-crates.rs index 5f9a5393c15..48e507757bb 100644 --- a/src/bin/transfer-crates.rs +++ b/src/bin/transfer-crates.rs @@ -69,11 +69,10 @@ fn transfer(tx: &postgres::transaction::Transaction) { let stmt = tx.prepare( - "SELECT * FROM crate_owners + "SELECT * FROM crate_owners WHERE owner_id = $1 - AND owner_kind = $2" - ) - .unwrap(); + AND owner_kind = $2", + ).unwrap(); let rows = stmt.query(&[&from.id, &(OwnerKind::User as i32)]).unwrap(); for row in rows.iter() { let id: i32 = row.get("id"); @@ -84,11 +83,10 @@ fn transfer(tx: &postgres::transaction::Transaction) { println!("warning: not exactly one owner for {}", krate.name); } let n = tx.execute( - "UPDATE crate_owners SET owner_id = $1 + "UPDATE crate_owners SET owner_id = $1 WHERE id $2", - &[&to.id, &id], - ) - .unwrap(); + &[&to.id, &id], + ).unwrap(); assert_eq!(n, 1); } diff --git a/src/bin/update-downloads.rs b/src/bin/update-downloads.rs index 67c64b91594..e89c1b94580 100644 --- a/src/bin/update-downloads.rs +++ b/src/bin/update-downloads.rs @@ -40,11 +40,11 @@ fn update(conn: &postgres::GenericConnection) -> postgres::Result<()> { tx = conn.transaction()?; { let stmt = tx.prepare( - "SELECT * FROM version_downloads \ + "SELECT * FROM version_downloads \ WHERE processed = FALSE AND id > $1 ORDER BY id ASC - LIMIT $2" - )?; + LIMIT $2", + )?; let mut rows = stmt.query(&[&max, &LIMIT])?; match collect(&tx, &mut rows)? { None => break, @@ -91,11 +91,11 @@ fn collect(tx: &postgres::transaction::Transaction, rows: &mut postgres::rows::R // Flag this row as having been processed if we're passed the cutoff, // and unconditionally increment the number of counted downloads. tx.execute( - "UPDATE version_downloads + "UPDATE version_downloads SET processed = $2, counted = counted + $3 WHERE id = $1", - &[id, &(download.date < cutoff), &amt], - )?; + &[id, &(download.date < cutoff), &amt], + )?; total += amt as i64; if amt == 0 { @@ -106,41 +106,41 @@ fn collect(tx: &postgres::transaction::Transaction, rows: &mut postgres::rows::R // Update the total number of version downloads tx.execute( - "UPDATE versions + "UPDATE versions SET downloads = downloads + $1 WHERE id = $2", - &[&amt, &download.version_id], - )?; + &[&amt, &download.version_id], + )?; // Update the total number of crate downloads tx.execute( - "UPDATE crates SET downloads = downloads + $1 + "UPDATE crates SET downloads = downloads + $1 WHERE id = $2", - &[&amt, &crate_id], - )?; + &[&amt, &crate_id], + )?; // Update the total number of crate downloads for today let cnt = tx.execute( - "UPDATE crate_downloads + "UPDATE crate_downloads SET downloads = downloads + $2 WHERE crate_id = $1 AND date = $3", - &[&crate_id, &amt, &download.date], - )?; + &[&crate_id, &amt, &download.date], + )?; if cnt == 0 { tx.execute( - "INSERT INTO crate_downloads + "INSERT INTO crate_downloads (crate_id, downloads, date) VALUES ($1, $2, $3)", - &[&crate_id, &amt, &download.date], - )?; + &[&crate_id, &amt, &download.date], + )?; } } // After everything else is done, update the global counter of total // downloads. tx.execute( - "UPDATE metadata SET total_downloads = total_downloads + $1", - &[&total], - )?; + "UPDATE metadata SET total_downloads = total_downloads + $1", + &[&total], + )?; Ok(Some(max)) } @@ -167,16 +167,12 @@ mod test { fn crate_downloads(tx: &postgres::transaction::Transaction, id: i32, expected: usize) { let stmt = tx.prepare( - "SELECT * FROM crate_downloads - WHERE crate_id = $1" - ) - .unwrap(); - let dl: i32 = stmt.query(&[&id]) - .unwrap() - .iter() - .next() - .unwrap() - .get("downloads"); + "SELECT * FROM crate_downloads + WHERE crate_id = $1", + ).unwrap(); + let dl: i32 = stmt.query(&[&id]).unwrap().iter().next().unwrap().get( + "downloads", + ); assert_eq!(dl, expected as i32); } @@ -197,30 +193,26 @@ mod test { &None, &None, None, - ) - .unwrap(); + ).unwrap(); let version = Version::insert( &tx, krate.id, &semver::Version::parse("1.0.0").unwrap(), &HashMap::new(), &[], - ) - .unwrap(); + ).unwrap(); tx.execute( - "INSERT INTO version_downloads \ + "INSERT INTO version_downloads \ (version_id) VALUES ($1)", - &[&version.id], - ) - .unwrap(); + &[&version.id], + ).unwrap(); tx.execute( - "INSERT INTO version_downloads \ + "INSERT INTO version_downloads \ (version_id, date, processed) VALUES ($1, current_date - interval '1 day', true)", - &[&version.id], - ) - .unwrap(); + &[&version.id], + ).unwrap(); ::update(&tx).unwrap(); assert_eq!(Version::find(&tx, version.id).unwrap().downloads, 1); assert_eq!(Crate::find(&tx, krate.id).unwrap().downloads, 1); @@ -246,29 +238,25 @@ mod test { &None, &None, None, - ) - .unwrap(); + ).unwrap(); let version = Version::insert( &tx, krate.id, &semver::Version::parse("1.0.0").unwrap(), &HashMap::new(), &[], - ) - .unwrap(); + ).unwrap(); tx.execute( - "INSERT INTO version_downloads \ + "INSERT INTO version_downloads \ (version_id, downloads, counted, date, processed) VALUES ($1, 2, 2, current_date - interval '2 days', false)", - &[&version.id], - ) - .unwrap(); + &[&version.id], + ).unwrap(); ::update(&tx).unwrap(); let stmt = tx.prepare( - "SELECT processed FROM version_downloads - WHERE version_id = $1" - ) - .unwrap(); + "SELECT processed FROM version_downloads + WHERE version_id = $1", + ).unwrap(); let processed: bool = stmt.query(&[&version.id]) .unwrap() .iter() @@ -295,30 +283,26 @@ mod test { &None, &None, None, - ) - .unwrap(); + ).unwrap(); let version = Version::insert( &tx, krate.id, &semver::Version::parse("1.0.0").unwrap(), &HashMap::new(), &[], - ) - .unwrap(); + ).unwrap(); let time = time::now_utc().to_timespec() - Duration::hours(2); tx.execute( - "INSERT INTO version_downloads \ + "INSERT INTO version_downloads \ (version_id, downloads, counted, date, processed) VALUES ($1, 2, 2, date($2), false)", - &[&version.id, &time], - ) - .unwrap(); + &[&version.id, &time], + ).unwrap(); ::update(&tx).unwrap(); let stmt = tx.prepare( - "SELECT processed FROM version_downloads - WHERE version_id = $1" - ) - .unwrap(); + "SELECT processed FROM version_downloads + WHERE version_id = $1", + ).unwrap(); let processed: bool = stmt.query(&[&version.id]) .unwrap() .iter() @@ -345,42 +329,36 @@ mod test { &None, &None, None, - ) - .unwrap(); + ).unwrap(); let version = Version::insert( &tx, krate.id, &semver::Version::parse("1.0.0").unwrap(), &HashMap::new(), &[], - ) - .unwrap(); + ).unwrap(); tx.execute( - "UPDATE versions + "UPDATE versions SET updated_at = current_date - interval '2 hours'", - &[], - ) - .unwrap(); + &[], + ).unwrap(); tx.execute( - "UPDATE crates + "UPDATE crates SET updated_at = current_date - interval '2 hours'", - &[], - ) - .unwrap(); + &[], + ).unwrap(); tx.execute( - "INSERT INTO version_downloads \ + "INSERT INTO version_downloads \ (version_id, downloads, counted, date, processed) VALUES ($1, 2, 1, current_date, false)", - &[&version.id], - ) - .unwrap(); + &[&version.id], + ).unwrap(); tx.execute( - "INSERT INTO version_downloads \ + "INSERT INTO version_downloads \ (version_id, date) VALUES ($1, current_date - interval '1 day')", - &[&version.id], - ) - .unwrap(); + &[&version.id], + ).unwrap(); let version_before = Version::find(&tx, version.id).unwrap(); let krate_before = Crate::find(&tx, krate.id).unwrap(); @@ -413,35 +391,30 @@ mod test { &None, &None, None, - ) - .unwrap(); + ).unwrap(); let version = Version::insert( &tx, krate.id, &semver::Version::parse("1.0.0").unwrap(), &HashMap::new(), &[], - ) - .unwrap(); + ).unwrap(); tx.execute( - "UPDATE versions + "UPDATE versions SET updated_at = current_date - interval '2 days'", - &[], - ) - .unwrap(); + &[], + ).unwrap(); tx.execute( - "UPDATE crates + "UPDATE crates SET updated_at = current_date - interval '2 days'", - &[], - ) - .unwrap(); + &[], + ).unwrap(); tx.execute( - "INSERT INTO version_downloads \ + "INSERT INTO version_downloads \ (version_id, downloads, counted, date, processed) VALUES ($1, 2, 2, current_date - interval '2 days', false)", - &[&version.id], - ) - .unwrap(); + &[&version.id], + ).unwrap(); let version_before = Version::find(&tx, version.id).unwrap(); let krate_before = Crate::find(&tx, krate.id).unwrap(); diff --git a/src/categories.rs b/src/categories.rs index 32abee2956e..83ea8017fc4 100644 --- a/src/categories.rs +++ b/src/categories.rs @@ -34,9 +34,12 @@ impl Category { } fn required_string_from_toml<'a>(toml: &'a toml::Table, key: &str) -> CargoResult<&'a str> { - toml.get(key) - .and_then(toml::Value::as_str) - .chain_error(|| internal(&format_args!("Expected category TOML attribute '{}' to be a String", key))) + toml.get(key).and_then(toml::Value::as_str).chain_error(|| { + internal(&format_args!( + "Expected category TOML attribute '{}' to be a String", + key + )) + }) } fn optional_string_from_toml<'a>(toml: &'a toml::Table, key: &str) -> &'a str { @@ -47,9 +50,9 @@ fn categories_from_toml(categories: &toml::Table, parent: Option<&Category>) -> let mut result = vec![]; for (slug, details) in categories { - let details = details - .as_table() - .chain_error(|| internal(&format_args!("category {} was not a TOML table", slug)))?; + let details = details.as_table().chain_error(|| { + internal(&format_args!("category {} was not a TOML table", slug)) + })?; let category = Category::from_parent( slug, @@ -59,9 +62,12 @@ fn categories_from_toml(categories: &toml::Table, parent: Option<&Category>) -> ); if let Some(categories) = details.get("categories") { - let categories = categories - .as_table() - .chain_error(|| internal(&format_args!("child categories of {} were not a table", slug)))?; + let categories = categories.as_table().chain_error(|| { + internal(&format_args!( + "child categories of {} were not a table", + slug + )) + })?; result.extend(categories_from_toml(categories, Some(&category))?); } @@ -77,22 +83,22 @@ pub fn sync() -> CargoResult<()> { let tx = conn.transaction().unwrap(); let categories = include_str!("./categories.toml"); - let toml = toml::Parser::new(categories) - .parse() - .expect("Could not parse categories.toml"); + let toml = toml::Parser::new(categories).parse().expect( + "Could not parse categories.toml", + ); let categories = categories_from_toml(&toml, None).expect("Could not convert categories from TOML"); for category in &categories { tx.execute( - "\ + "\ INSERT INTO categories (slug, category, description) \ VALUES (LOWER($1), $2, $3) \ ON CONFLICT (slug) DO UPDATE \ SET category = EXCLUDED.category, \ description = EXCLUDED.description;", - &[&category.slug, &category.name, &category.description], - )?; + &[&category.slug, &category.name, &category.description], + )?; } let in_clause = categories @@ -102,12 +108,14 @@ pub fn sync() -> CargoResult<()> { .join(","); tx.execute( - &format!("\ + &format!( + "\ DELETE FROM categories \ WHERE slug NOT IN ({});", - in_clause), - &[], - )?; + in_clause + ), + &[], + )?; tx.set_commit(); tx.finish().unwrap(); Ok(()) diff --git a/src/category.rs b/src/category.rs index 9f5d63f9fff..90a649aceca 100644 --- a/src/category.rs +++ b/src/category.rs @@ -15,7 +15,7 @@ use util::{RequestUtils, CargoResult, ChainError}; use {Model, Crate}; #[derive(Clone, Identifiable, Queryable)] -#[table_name="categories"] +#[table_name = "categories"] pub struct Category { pub id: i32, pub category: String, @@ -28,7 +28,7 @@ pub struct Category { #[derive(Associations, Insertable, Identifiable)] #[belongs_to(Category)] #[belongs_to(Crate)] -#[table_name="crates_categories"] +#[table_name = "crates_categories"] #[primary_key(crate_id, category_id)] pub struct CrateCategory { crate_id: i32, @@ -59,26 +59,24 @@ pub struct EncodableCategoryWithSubcategories { impl Category { pub fn find_by_category(conn: &GenericConnection, name: &str) -> CargoResult { let stmt = conn.prepare( - "SELECT * FROM categories \ - WHERE category = $1" - )?; + "SELECT * FROM categories \ + WHERE category = $1", + )?; let rows = stmt.query(&[&name])?; - rows.iter() - .next() - .chain_error(|| NotFound) - .map(|row| Model::from_row(&row)) + rows.iter().next().chain_error(|| NotFound).map(|row| { + Model::from_row(&row) + }) } pub fn find_by_slug(conn: &GenericConnection, slug: &str) -> CargoResult { let stmt = conn.prepare( - "SELECT * FROM categories \ - WHERE slug = LOWER($1)" - )?; + "SELECT * FROM categories \ + WHERE slug = LOWER($1)", + )?; let rows = stmt.query(&[&slug])?; - rows.iter() - .next() - .chain_error(|| NotFound) - .map(|row| Model::from_row(&row)) + rows.iter().next().chain_error(|| NotFound).map(|row| { + Model::from_row(&row) + }) } pub fn encodable(self) -> EncodableCategory { @@ -103,35 +101,31 @@ impl Category { pub fn update_crate<'a>(conn: &PgConnection, krate: &Crate, slugs: &[&'a str]) -> QueryResult> { use diesel::expression::dsl::any; - conn.transaction( - || { - let categories = categories::table - .filter(categories::slug.eq(any(slugs))) - .load::(conn)?; - let invalid_categories = slugs - .iter() - .cloned() - .filter(|s| !categories.iter().any(|c| c.slug == *s)) - .collect(); - let crate_categories = categories - .iter() - .map( - |c| { - CrateCategory { - category_id: c.id, - crate_id: krate.id, - } - } - ) - .collect::>(); - - delete(CrateCategory::belonging_to(krate)).execute(conn)?; - insert(&crate_categories) - .into(crates_categories::table) - .execute(conn)?; - Ok(invalid_categories) - } - ) + conn.transaction(|| { + let categories = categories::table + .filter(categories::slug.eq(any(slugs))) + .load::(conn)?; + let invalid_categories = slugs + .iter() + .cloned() + .filter(|s| !categories.iter().any(|c| c.slug == *s)) + .collect(); + let crate_categories = categories + .iter() + .map(|c| { + CrateCategory { + category_id: c.id, + crate_id: krate.id, + } + }) + .collect::>(); + + delete(CrateCategory::belonging_to(krate)).execute(conn)?; + insert(&crate_categories) + .into(crates_categories::table) + .execute(conn)?; + Ok(invalid_categories) + }) } pub fn update_crate_old(conn: &GenericConnection, krate: &Crate, categories: &[String]) -> CargoResult> { @@ -143,15 +137,13 @@ impl Category { let mut invalid_categories = vec![]; let new_categories: Vec = categories .iter() - .flat_map( - |c| match Category::find_by_slug(conn, c) { - Ok(cat) => Some(cat), - Err(_) => { - invalid_categories.push(c.to_string()); - None - } + .flat_map(|c| match Category::find_by_slug(conn, c) { + Ok(cat) => Some(cat), + Err(_) => { + invalid_categories.push(c.to_string()); + None } - ) + }) .collect(); let new_categories_ids: HashSet<_> = new_categories.iter().map(|cat| cat.id).collect(); @@ -167,11 +159,11 @@ impl Category { if !to_rm.is_empty() { conn.execute( - "DELETE FROM crates_categories \ + "DELETE FROM crates_categories \ WHERE category_id = ANY($1) \ AND crate_id = $2", - &[&to_rm, &krate.id], - )?; + &[&to_rm, &krate.id], + )?; } if !to_add.is_empty() { @@ -181,23 +173,26 @@ impl Category { .collect(); let insert = insert.join(", "); conn.execute( - &format!("INSERT INTO crates_categories \ + &format!( + "INSERT INTO crates_categories \ (crate_id, category_id) VALUES {}", - insert), - &[], - )?; + insert + ), + &[], + )?; } Ok(invalid_categories) } pub fn count_toplevel(conn: &GenericConnection) -> CargoResult { - let sql = format!("\ + let sql = format!( + "\ SELECT COUNT(*) \ FROM {} \ WHERE category NOT LIKE '%::%'", - Model::table_name(None:: - )); + Model::table_name(None::) + ); let stmt = conn.prepare(&sql)?; let rows = stmt.query(&[])?; Ok(rows.iter().next().unwrap().get("count")) @@ -214,9 +209,7 @@ impl Category { // Collect all the top-level categories and sum up the crates_cnt of // the crates in all subcategories - select( - sql::( - &format!( + select(sql::(&format!( "c.id, c.category, c.slug, c.description, sum(c2.crates_cnt)::int as crates_cnt, c.created_at FROM categories as c @@ -224,11 +217,10 @@ impl Category { WHERE split_part(c.slug, '::', 1) = c.slug GROUP BY c.id {} LIMIT {} OFFSET {}", - sort_sql, limit, offset - ) - ) - ) - .load(conn) + sort_sql, + limit, + offset + ))).load(conn) } pub fn toplevel_old(conn: &GenericConnection, sort: &str, limit: i64, offset: i64) -> CargoResult> { @@ -240,8 +232,7 @@ impl Category { // Collect all the top-level categories and sum up the crates_cnt of // the crates in all subcategories - let stmt = conn.prepare( - &format!( + let stmt = conn.prepare(&format!( "SELECT c.id, c.category, c.slug, c.description, c.created_at, sum(c2.crates_cnt)::int as crates_cnt FROM categories as c @@ -250,8 +241,7 @@ impl Category { GROUP BY c.id {} LIMIT $1 OFFSET $2", sort_sql - ) - )?; + ))?; let categories: Vec<_> = stmt.query(&[&limit, &offset])? .iter() @@ -263,7 +253,7 @@ impl Category { pub fn subcategories(&self, conn: &GenericConnection) -> CargoResult> { let stmt = conn.prepare( - "\ + "\ SELECT c.id, c.category, c.slug, c.description, c.created_at, \ COALESCE (( \ SELECT sum(c2.crates_cnt)::int \ @@ -273,8 +263,8 @@ impl Category { ), 0) as crates_cnt \ FROM categories as c \ WHERE c.category ILIKE $1 || '::%' \ - AND c.category NOT ILIKE $1 || '::%::%'" - )?; + AND c.category NOT ILIKE $1 || '::%::%'", + )?; let rows = stmt.query(&[&self.category])?; Ok(rows.iter().map(|r| Model::from_row(&r)).collect()) @@ -282,7 +272,7 @@ impl Category { } #[derive(Insertable, Default)] -#[table_name="categories"] +#[table_name = "categories"] pub struct NewCategory<'a> { pub category: &'a str, pub slug: &'a str, @@ -345,14 +335,10 @@ pub fn index(req: &mut Request) -> CargoResult { total: i64, } - Ok( - req.json( - &R { - categories: categories, - meta: Meta { total: total }, - } - ) - ) + Ok(req.json(&R { + categories: categories, + meta: Meta { total: total }, + })) } /// Handles the `GET /categories/:category_id` route. @@ -386,9 +372,9 @@ pub fn show(req: &mut Request) -> CargoResult { pub fn slugs(req: &mut Request) -> CargoResult { let conn = req.tx()?; let stmt = conn.prepare( - "SELECT slug FROM categories \ - ORDER BY slug" - )?; + "SELECT slug FROM categories \ + ORDER BY slug", + )?; let rows = stmt.query(&[])?; #[derive(RustcEncodable)] @@ -398,15 +384,13 @@ pub fn slugs(req: &mut Request) -> CargoResult { } let slugs: Vec = rows.iter() - .map( - |r| { - let slug: String = r.get("slug"); - Slug { - id: slug.clone(), - slug: slug, - } + .map(|r| { + let slug: String = r.get("slug"); + Slug { + id: slug.clone(), + slug: slug, } - ) + }) .collect(); #[derive(RustcEncodable)] @@ -437,11 +421,10 @@ mod tests { fn category_toplevel_excludes_subcategories() { let conn = pg_connection(); conn.batch_execute( - "INSERT INTO categories (category, slug) VALUES + "INSERT INTO categories (category, slug) VALUES ('Cat 2', 'cat2'), ('Cat 1', 'cat1'), ('Cat 1::sub', 'cat1::sub') - " - ) - .unwrap(); + ", + ).unwrap(); let categories = Category::toplevel(&conn, "", 10, 0) .unwrap() @@ -456,18 +439,21 @@ mod tests { fn category_toplevel_orders_by_crates_cnt_when_sort_given() { let conn = pg_connection(); conn.batch_execute( - "INSERT INTO categories (category, slug, crates_cnt) VALUES + "INSERT INTO categories (category, slug, crates_cnt) VALUES ('Cat 1', 'cat1', 0), ('Cat 2', 'cat2', 2), ('Cat 3', 'cat3', 1) - " - ) - .unwrap(); + ", + ).unwrap(); let categories = Category::toplevel(&conn, "crates", 10, 0) .unwrap() .into_iter() .map(|c| c.category) .collect::>(); - let expected = vec!["Cat 2".to_string(), "Cat 3".to_string(), "Cat 1".to_string()]; + let expected = vec![ + "Cat 2".to_string(), + "Cat 3".to_string(), + "Cat 1".to_string(), + ]; assert_eq!(expected, categories); } @@ -475,11 +461,10 @@ mod tests { fn category_toplevel_applies_limit_and_offset() { let conn = pg_connection(); conn.batch_execute( - "INSERT INTO categories (category, slug) VALUES + "INSERT INTO categories (category, slug) VALUES ('Cat 1', 'cat1'), ('Cat 2', 'cat2') - " - ) - .unwrap(); + ", + ).unwrap(); let categories = Category::toplevel(&conn, "", 1, 0) .unwrap() @@ -502,13 +487,12 @@ mod tests { fn category_toplevel_includes_subcategories_in_crate_cnt() { let conn = pg_connection(); conn.batch_execute( - "INSERT INTO categories (category, slug, crates_cnt) VALUES + "INSERT INTO categories (category, slug, crates_cnt) VALUES ('Cat 1', 'cat1', 1), ('Cat 1::sub', 'cat1::sub', 2), ('Cat 2', 'cat2', 3), ('Cat 2::Sub 1', 'cat2::sub1', 4), ('Cat 2::Sub 2', 'cat2::sub2', 5), ('Cat 3', 'cat3', 6) - " - ) - .unwrap(); + ", + ).unwrap(); let categories = Category::toplevel(&conn, "crates", 10, 0) .unwrap() @@ -527,23 +511,19 @@ mod tests { fn category_toplevel_applies_limit_and_offset_after_grouping() { let conn = pg_connection(); conn.batch_execute( - "INSERT INTO categories (category, slug, crates_cnt) VALUES + "INSERT INTO categories (category, slug, crates_cnt) VALUES ('Cat 1', 'cat1', 1), ('Cat 1::sub', 'cat1::sub', 2), ('Cat 2', 'cat2', 3), ('Cat 2::Sub 1', 'cat2::sub1', 4), ('Cat 2::Sub 2', 'cat2::sub2', 5), ('Cat 3', 'cat3', 6) - " - ) - .unwrap(); + ", + ).unwrap(); let categories = Category::toplevel(&conn, "crates", 2, 0) .unwrap() .into_iter() .map(|c| (c.category, c.crates_cnt)) .collect::>(); - let expected = vec![ - ("Cat 2".to_string(), 12), - ("Cat 3".to_string(), 6), - ]; + let expected = vec![("Cat 2".to_string(), 12), ("Cat 3".to_string(), 6)]; assert_eq!(expected, categories); let categories = Category::toplevel(&conn, "crates", 2, 1) @@ -551,10 +531,7 @@ mod tests { .into_iter() .map(|c| (c.category, c.crates_cnt)) .collect::>(); - let expected = vec![ - ("Cat 3".to_string(), 6), - ("Cat 1".to_string(), 3), - ]; + let expected = vec![("Cat 3".to_string(), 6), ("Cat 1".to_string(), 3)]; assert_eq!(expected, categories); } } diff --git a/src/db.rs b/src/db.rs index 0e697ffdb31..e139f9b2c32 100644 --- a/src/db.rs +++ b/src/db.rs @@ -142,10 +142,9 @@ impl Transaction { pub fn conn(&self) -> CargoResult<&r2d2::PooledConnection> { if !self.slot.filled() { - let conn = self.app - .database - .get() - .map_err(|e| internal(&format_args!("failed to get a database connection: {}", e)))?; + let conn = self.app.database.get().map_err(|e| { + internal(&format_args!("failed to get a database connection: {}", e)) + })?; self.slot.fill(Box::new(conn)); } Ok(&**self.slot.borrow().unwrap()) @@ -188,16 +187,16 @@ impl Middleware for TransactionMiddleware { } fn after(&self, req: &mut Request, res: Result>) -> Result> { - let tx = req.mut_extensions() - .pop::() - .expect("Transaction not present in request"); + let tx = req.mut_extensions().pop::().expect( + "Transaction not present in request", + ); if let Some(transaction) = tx.tx.into_inner() { if res.is_ok() && tx.commit.get() == Some(true) { transaction.set_commit(); } - transaction - .finish() - .map_err(|e| Box::new(e) as Box)?; + transaction.finish().map_err( + |e| Box::new(e) as Box, + )?; } res } diff --git a/src/dependency.rs b/src/dependency.rs index 0ceefa31160..b482d9f40cb 100644 --- a/src/dependency.rs +++ b/src/dependency.rs @@ -14,7 +14,7 @@ use version::Version; #[derive(Identifiable, Associations)] #[belongs_to(Version)] #[belongs_to(Crate)] -#[table_name="dependencies"] +#[table_name = "dependencies"] pub struct Dependency { pub id: i32, pub version_id: i32, @@ -57,7 +57,7 @@ pub enum Kind { } #[derive(Default, Insertable)] -#[table_name="dependencies"] +#[table_name = "dependencies"] pub struct NewDependency<'a> { pub version_id: i32, pub crate_id: i32, @@ -85,24 +85,24 @@ impl Dependency { ) -> CargoResult { let req = req.to_string(); let stmt = conn.prepare( - "INSERT INTO dependencies + "INSERT INTO dependencies (version_id, crate_id, req, optional, default_features, features, target, kind) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) - RETURNING *" - )?; + RETURNING *", + )?; let rows = stmt.query( - &[ - &version_id, - &crate_id, - &req, - &optional, - &default_features, - &features, - target, - &(kind as i32), - ] - )?; + &[ + &version_id, + &crate_id, + &req, + &optional, + &default_features, + &features, + target, + &(kind as i32), + ], + )?; Ok(Model::from_row(&rows.iter().next().unwrap())) } @@ -125,8 +125,10 @@ impl Dependency { impl ReverseDependency { pub fn encodable(self) -> EncodableDependency { - self.dependency - .encodable(&self.crate_name, Some(self.crate_downloads)) + self.dependency.encodable( + &self.crate_name, + Some(self.crate_downloads), + ) } } @@ -134,46 +136,44 @@ pub fn add_dependencies(conn: &PgConnection, deps: &[::upload::CrateDependency], use diesel::insert; let git_and_new_dependencies = deps.iter() - .map( - |dep| { - let krate = Crate::by_name(&dep.name) - .first::(&*conn) - .map_err(|_| human(&format_args!("no known crate named `{}`", &*dep.name)))?; - if dep.version_req == semver::VersionReq::parse("*").unwrap() { - return Err( - human( - "wildcard (`*`) dependency constraints are not allowed \ + .map(|dep| { + let krate = Crate::by_name(&dep.name).first::(&*conn).map_err( + |_| { + human(&format_args!("no known crate named `{}`", &*dep.name)) + }, + )?; + if dep.version_req == semver::VersionReq::parse("*").unwrap() { + return Err(human( + "wildcard (`*`) dependency constraints are not allowed \ on crates.io. See http://doc.crates.io/faq.html#can-\ libraries-use--as-a-version-for-their-dependencies for more \ - information" - ) - ); - } - let features: Vec<_> = dep.features.iter().map(|s| &**s).collect(); - - Ok( - (git::Dependency { - name: dep.name.to_string(), - req: dep.version_req.to_string(), - features: features.iter().map(|s| s.to_string()).collect(), - optional: dep.optional, - default_features: dep.default_features, - target: dep.target.clone(), - kind: dep.kind.or(Some(Kind::Normal)), - }, - NewDependency { - version_id: version_id, - crate_id: krate.id, - req: dep.version_req.to_string(), - kind: dep.kind.unwrap_or(Kind::Normal) as i32, - optional: dep.optional, - default_features: dep.default_features, - features: features, - target: dep.target.as_ref().map(|s| &**s), - }) - ) + information", + )); } - ) + let features: Vec<_> = dep.features.iter().map(|s| &**s).collect(); + + Ok(( + git::Dependency { + name: dep.name.to_string(), + req: dep.version_req.to_string(), + features: features.iter().map(|s| s.to_string()).collect(), + optional: dep.optional, + default_features: dep.default_features, + target: dep.target.clone(), + kind: dep.kind.or(Some(Kind::Normal)), + }, + NewDependency { + version_id: version_id, + crate_id: krate.id, + req: dep.version_req.to_string(), + kind: dep.kind.unwrap_or(Kind::Normal) as i32, + optional: dep.optional, + default_features: dep.default_features, + features: features, + target: dep.target.as_ref().map(|s| &**s), + }, + )) + }) .collect::, _>>()?; let (git_deps, new_dependencies): (Vec<_>, Vec<_>) = git_and_new_dependencies.into_iter().unzip(); diff --git a/src/dist.rs b/src/dist.rs index 1d3aac80f53..ba83b84d20f 100644 --- a/src/dist.rs +++ b/src/dist.rs @@ -42,14 +42,11 @@ impl Handler for Middleware { .map(|accept| accept.iter().any(|s| s.contains("html"))) .unwrap_or(false); if wants_html { - self.dist - .call( - &mut RequestProxy { - other: req, - path: Some("/index.html"), - method: None, - } - ) + self.dist.call(&mut RequestProxy { + other: req, + path: Some("/index.html"), + method: None, + }) } else { self.handler.as_ref().unwrap().call(req) } diff --git a/src/download.rs b/src/download.rs index 3e54c6ba76f..d83350bbbb2 100644 --- a/src/download.rs +++ b/src/download.rs @@ -20,7 +20,7 @@ pub struct VersionDownload { } #[derive(Insertable)] -#[table_name="version_downloads"] +#[table_name = "version_downloads"] struct NewVersionDownload( #[column_name(version_id)] i32 diff --git a/src/git.rs b/src/git.rs index 33ad587d075..810e16b5855 100644 --- a/src/git.rs +++ b/src/git.rs @@ -51,24 +51,26 @@ pub fn add_crate(app: &App, krate: &Crate) -> CargoResult<()> { let repo_path = repo.workdir().unwrap(); let dst = index_file(repo_path, &krate.name); - commit_and_push( - repo, || { - // Add the crate to its relevant file - fs::create_dir_all(dst.parent().unwrap())?; - let mut prev = String::new(); - if fs::metadata(&dst).is_ok() { - File::open(&dst) - .and_then(|mut f| f.read_to_string(&mut prev))?; - } - let s = json::encode(krate).unwrap(); - let new = prev + &s; - let mut f = File::create(&dst)?; - f.write_all(new.as_bytes())?; - f.write_all(b"\n")?; - - Ok((format!("Updating crate `{}#{}`", krate.name, krate.vers), dst.clone())) + commit_and_push(repo, || { + // Add the crate to its relevant file + fs::create_dir_all(dst.parent().unwrap())?; + let mut prev = String::new(); + if fs::metadata(&dst).is_ok() { + File::open(&dst).and_then( + |mut f| f.read_to_string(&mut prev), + )?; } - ) + let s = json::encode(krate).unwrap(); + let new = prev + &s; + let mut f = File::create(&dst)?; + f.write_all(new.as_bytes())?; + f.write_all(b"\n")?; + + Ok(( + format!("Updating crate `{}#{}`", krate.name, krate.vers), + dst.clone(), + )) + }) } pub fn yank(app: &App, krate: &str, version: &semver::Version, yanked: bool) -> CargoResult<()> { @@ -76,37 +78,38 @@ pub fn yank(app: &App, krate: &str, version: &semver::Version, yanked: bool) -> let repo_path = repo.workdir().unwrap(); let dst = index_file(repo_path, krate); - commit_and_push( - &repo, || { - let mut prev = String::new(); - File::open(&dst) - .and_then(|mut f| f.read_to_string(&mut prev))?; - let new = prev.lines() - .map( - |line| { - let mut git_crate = json::decode::(line) - .map_err(|_| internal(&format_args!("couldn't decode: `{}`", line)))?; - if git_crate.name != krate || git_crate.vers != version.to_string() { - return Ok(line.to_string()); - } - git_crate.yanked = Some(yanked); - Ok(json::encode(&git_crate).unwrap()) - } - ) - .collect::>>(); - let new = new?.join("\n"); - let mut f = File::create(&dst)?; - f.write_all(new.as_bytes())?; - f.write_all(b"\n")?; - - Ok( - (format!("{} crate `{}#{}`", - if yanked {"Yanking"} else {"Unyanking"}, - krate, version), - dst.clone()) - ) - } - ) + commit_and_push(&repo, || { + let mut prev = String::new(); + File::open(&dst).and_then( + |mut f| f.read_to_string(&mut prev), + )?; + let new = prev.lines() + .map(|line| { + let mut git_crate = json::decode::(line).map_err(|_| { + internal(&format_args!("couldn't decode: `{}`", line)) + })?; + if git_crate.name != krate || git_crate.vers != version.to_string() { + return Ok(line.to_string()); + } + git_crate.yanked = Some(yanked); + Ok(json::encode(&git_crate).unwrap()) + }) + .collect::>>(); + let new = new?.join("\n"); + let mut f = File::create(&dst)?; + f.write_all(new.as_bytes())?; + f.write_all(b"\n")?; + + Ok(( + format!( + "{} crate `{}#{}`", + if yanked { "Yanking" } else { "Unyanking" }, + krate, + version + ), + dst.clone(), + )) + }) } fn commit_and_push(repo: &git2::Repository, mut f: F) -> CargoResult<()> @@ -137,7 +140,14 @@ where let head = repo.head()?; let parent = repo.find_commit(head.target().unwrap())?; let sig = repo.signature()?; - repo.commit(Some("HEAD"), &sig, &sig, &msg, &tree, &[&parent])?; + repo.commit( + Some("HEAD"), + &sig, + &sig, + &msg, + &tree, + &[&parent], + )?; // git push let mut ref_status = None; @@ -145,13 +155,11 @@ where let res = { let mut callbacks = git2::RemoteCallbacks::new(); callbacks.credentials(credentials); - callbacks.push_update_reference( - |refname, status| { - assert_eq!(refname, "refs/heads/master"); - ref_status = status.map(|s| s.to_string()); - Ok(()) - } - ); + callbacks.push_update_reference(|refname, status| { + assert_eq!(refname, "refs/heads/master"); + ref_status = status.map(|s| s.to_string()); + Ok(()) + }); let mut opts = git2::PushOptions::new(); opts.remote_callbacks(callbacks); origin.push(&["refs/heads/master"], Some(&mut opts)) @@ -164,13 +172,12 @@ where let mut callbacks = git2::RemoteCallbacks::new(); callbacks.credentials(credentials); - origin - .update_tips( - Some(&mut callbacks), - true, - git2::AutotagOption::Unspecified, - None, - )?; + origin.update_tips( + Some(&mut callbacks), + true, + git2::AutotagOption::Unspecified, + None, + )?; // Ok, we need to update, so fetch and reset --hard origin.fetch(&["refs/heads/*:refs/heads/*"], None, None)?; diff --git a/src/http.rs b/src/http.rs index 3e3e9c20d0a..4767239958a 100644 --- a/src/http.rs +++ b/src/http.rs @@ -32,12 +32,10 @@ pub fn github(app: &App, url: &str, auth: &Token) -> Result<(Easy, Vec), cur { let mut transfer = handle.transfer(); transfer - .write_function( - |buf| { - data.extend_from_slice(buf); - Ok(buf.len()) - } - ) + .write_function(|buf| { + data.extend_from_slice(buf); + Ok(buf.len()) + }) .unwrap(); transfer.perform()?; } @@ -49,32 +47,30 @@ pub fn parse_github_response(mut resp: Easy, data: &[u8]) -> Cargo match resp.response_code().unwrap() { 200 => {} // Ok! 403 => { - return Err( - human( - "It looks like you don't have permission \ + return Err(human( + "It looks like you don't have permission \ to query a necessary property from Github \ to complete this request. \ You may need to re-authenticate on \ crates.io to grant permission to read \ github org memberships. Just go to \ - https://crates.io/login" - ) - ); + https://crates.io/login", + )); } n => { let resp = String::from_utf8_lossy(data); - return Err( - internal( - &format_args!("didn't get a 200 result from \ - github, got {} with: {}", n, resp) - ) - ); + return Err(internal(&format_args!( + "didn't get a 200 result from \ + github, got {} with: {}", + n, + resp + ))); } } - let json = str::from_utf8(data) - .ok() - .chain_error(|| internal("github didn't send a utf8-response"))?; + let json = str::from_utf8(data).ok().chain_error(|| { + internal("github didn't send a utf8-response") + })?; json::decode(json).chain_error(|| internal("github didn't send a valid json response")) } diff --git a/src/keyword.rs b/src/keyword.rs index b3cbfed7142..0b7990eac10 100644 --- a/src/keyword.rs +++ b/src/keyword.rs @@ -24,7 +24,7 @@ pub struct Keyword { #[derive(Associations, Insertable, Identifiable)] #[belongs_to(Keyword)] #[belongs_to(Crate)] -#[table_name="crates_keywords"] +#[table_name = "crates_keywords"] #[primary_key(crate_id, keyword_id)] pub struct CrateKeyword { crate_id: i32, @@ -51,7 +51,7 @@ impl Keyword { use diesel::expression::dsl::any; #[derive(Insertable)] - #[table_name="keywords"] + #[table_name = "keywords"] struct NewKeyword<'a> { keyword: &'a str, } @@ -79,8 +79,9 @@ impl Keyword { return false; } name.chars().next().unwrap().is_alphanumeric() && - name.chars() - .all(|c| c.is_alphanumeric() || c == '_' || c == '-') && name.chars().all(|c| c.is_ascii()) + name.chars().all( + |c| c.is_alphanumeric() || c == '_' || c == '-', + ) && name.chars().all(|c| c.is_ascii()) } pub fn encodable(self) -> EncodableKeyword { @@ -99,28 +100,25 @@ impl Keyword { } pub fn update_crate(conn: &PgConnection, krate: &Crate, keywords: &[&str]) -> QueryResult<()> { - conn.transaction( - || { - let keywords = Keyword::find_or_create_all(conn, keywords)?; - diesel::delete(CrateKeyword::belonging_to(krate)) - .execute(conn)?; - let crate_keywords = keywords - .into_iter() - .map( - |kw| { - CrateKeyword { - crate_id: krate.id, - keyword_id: kw.id, - } - } - ) - .collect::>(); - diesel::insert(&crate_keywords) - .into(crates_keywords::table) - .execute(conn)?; - Ok(()) - } - ) + conn.transaction(|| { + let keywords = Keyword::find_or_create_all(conn, keywords)?; + diesel::delete(CrateKeyword::belonging_to(krate)).execute( + conn, + )?; + let crate_keywords = keywords + .into_iter() + .map(|kw| { + CrateKeyword { + crate_id: krate.id, + keyword_id: kw.id, + } + }) + .collect::>(); + diesel::insert(&crate_keywords) + .into(crates_keywords::table) + .execute(conn)?; + Ok(()) + }) } } @@ -177,14 +175,10 @@ pub fn index(req: &mut Request) -> CargoResult { total: i64, } - Ok( - req.json( - &R { - keywords: kws, - meta: Meta { total: total }, - } - ) - ) + Ok(req.json(&R { + keywords: kws, + meta: Meta { total: total }, + })) } /// Handles the `GET /keywords/:keyword_id` route. diff --git a/src/krate.rs b/src/krate.rs index a3953298668..cb77d4b3be9 100644 --- a/src/krate.rs +++ b/src/krate.rs @@ -69,18 +69,20 @@ type AllColumns = (crates::id, crates::repository, crates::max_upload_size); -pub const ALL_COLUMNS: AllColumns = (crates::id, - crates::name, - crates::updated_at, - crates::created_at, - crates::downloads, - crates::description, - crates::homepage, - crates::documentation, - crates::readme, - crates::license, - crates::repository, - crates::max_upload_size); +pub const ALL_COLUMNS: AllColumns = ( + crates::id, + crates::name, + crates::updated_at, + crates::created_at, + crates::downloads, + crates::description, + crates::homepage, + crates::documentation, + crates::readme, + crates::license, + crates::repository, + crates::max_upload_size, +); pub const MAX_NAME_LENGTH: usize = 64; @@ -116,7 +118,7 @@ pub struct CrateLinks { } #[derive(Insertable, AsChangeset, Default)] -#[table_name="crates"] +#[table_name = "crates"] #[primary_key(name, max_upload_size)] // This is actually just to skip updating them pub struct NewCrate<'a> { pub name: &'a str, @@ -136,22 +138,22 @@ impl<'a> NewCrate<'a> { self.validate(license_file)?; self.ensure_name_not_reserved(conn)?; - conn.transaction( - || { - // To avoid race conditions, we try to insert - // first so we know whether to add an owner - if let Some(krate) = self.save_new_crate(conn, uploader)? { - return Ok(krate); - } - - let target = crates::table.filter(canon_crate_name(crates::name).eq(canon_crate_name(self.name))); - update(target) - .set(&self) - .returning(ALL_COLUMNS) - .get_result(conn) - .map_err(Into::into) + conn.transaction(|| { + // To avoid race conditions, we try to insert + // first so we know whether to add an owner + if let Some(krate) = self.save_new_crate(conn, uploader)? { + return Ok(krate); } - ) + + let target = crates::table.filter(canon_crate_name(crates::name).eq( + canon_crate_name(self.name), + )); + update(target) + .set(&self) + .returning(ALL_COLUMNS) + .get_result(conn) + .map_err(Into::into) + }) } fn validate(&mut self, license_file: Option<&str>) -> CargoResult<()> { @@ -160,26 +162,27 @@ impl<'a> NewCrate<'a> { Some(s) => s, None => return Ok(()), }; - let url = Url::parse(url) - .map_err(|_| human(&format_args!("`{}` is not a valid url: `{}`", field, url)))?; + let url = Url::parse(url).map_err(|_| { + human(&format_args!("`{}` is not a valid url: `{}`", field, url)) + })?; match &url.scheme()[..] { "http" | "https" => {} s => { - return Err( - human( - &format_args!("`{}` has an invalid url \ - scheme: `{}`", field, s) - ) - ) + return Err(human(&format_args!( + "`{}` has an invalid url \ + scheme: `{}`", + field, + s + ))) } } if url.cannot_be_a_base() { - return Err( - human( - &format_args!("`{}` must have relative scheme \ - data: {}", field, url) - ) - ); + return Err(human(&format_args!( + "`{}` must have relative scheme \ + data: {}", + field, + url + ))); } Ok(()) } @@ -194,16 +197,14 @@ impl<'a> NewCrate<'a> { fn validate_license(&mut self, license_file: Option<&str>) -> CargoResult<()> { if let Some(license) = self.license { for part in license.split('/') { - license_exprs::validate_license_expr(part) - .map_err( - |e| { - human( - &format_args!("{}; see http://opensource.org/licenses \ + license_exprs::validate_license_expr(part).map_err(|e| { + human(&format_args!( + "{}; see http://opensource.org/licenses \ for options, and http://spdx.org/licenses/ \ - for their identifiers", e) - ) - } - )?; + for their identifiers", + e + )) + })?; } } else if license_file.is_some() { // If no license is given, but a license file is given, flag this @@ -219,8 +220,13 @@ impl<'a> NewCrate<'a> { use diesel::select; use diesel::expression::dsl::exists; - let reserved_name = select(exists(reserved_crate_names.filter(canon_crate_name(name).eq(canon_crate_name(self.name))))) - .get_result::(conn)?; + let reserved_name = select(exists( + reserved_crate_names.filter(canon_crate_name(name).eq( + canon_crate_name( + self.name, + ), + )), + )).get_result::(conn)?; if reserved_name { Err(human("cannot upload a crate with a reserved name")) } else { @@ -232,27 +238,25 @@ impl<'a> NewCrate<'a> { use schema::crates::dsl::*; use diesel::insert; - conn.transaction( - || { - let maybe_inserted = insert(&self.on_conflict_do_nothing()) - .into(crates) - .returning(ALL_COLUMNS) - .get_result::(conn) - .optional()?; - - if let Some(ref krate) = maybe_inserted { - let owner = CrateOwner { - crate_id: krate.id, - owner_id: user_id, - created_by: user_id, - owner_kind: OwnerKind::User as i32, - }; - insert(&owner).into(crate_owners::table).execute(conn)?; - } - - Ok(maybe_inserted) + conn.transaction(|| { + let maybe_inserted = insert(&self.on_conflict_do_nothing()) + .into(crates) + .returning(ALL_COLUMNS) + .get_result::(conn) + .optional()?; + + if let Some(ref krate) = maybe_inserted { + let owner = CrateOwner { + crate_id: krate.id, + owner_id: user_id, + created_by: user_id, + owner_kind: OwnerKind::User as i32, + }; + insert(&owner).into(crate_owners::table).execute(conn)?; } - ) + + Ok(maybe_inserted) + }) } } @@ -269,10 +273,10 @@ impl Crate { pub fn find_by_name(conn: &GenericConnection, name: &str) -> CargoResult { let stmt = conn.prepare( - "SELECT * FROM crates \ + "SELECT * FROM crates \ WHERE canon_crate_name(name) = - canon_crate_name($1) LIMIT 1" - )?; + canon_crate_name($1) LIMIT 1", + )?; let rows = stmt.query(&[&name])?; let row = rows.iter().next(); let row = row.chain_error(|| NotFound)?; @@ -322,7 +326,7 @@ impl Crate { // TODO: like with users, this is sadly racy let stmt = conn.prepare( - "UPDATE crates + "UPDATE crates SET documentation = $1, homepage = $2, description = $3, @@ -331,65 +335,63 @@ impl Crate { repository = $6 WHERE canon_crate_name(name) = canon_crate_name($7) - RETURNING *" - )?; + RETURNING *", + )?; let rows = stmt.query( - &[ - &documentation, - &homepage, - &description, - &readme, - &license, - &repository, - &name, - ] - )?; + &[ + &documentation, + &homepage, + &description, + &readme, + &license, + &repository, + &name, + ], + )?; if let Some(row) = rows.iter().next() { return Ok(Model::from_row(&row)); } let stmt = conn.prepare( - "SELECT 1 FROM reserved_crate_names + "SELECT 1 FROM reserved_crate_names WHERE canon_crate_name(name) = - canon_crate_name($1)" - )?; + canon_crate_name($1)", + )?; let rows = stmt.query(&[&name])?; if !rows.is_empty() { return Err(human("cannot upload a crate with a reserved name")); } let stmt = conn.prepare( - "INSERT INTO crates + "INSERT INTO crates (name, description, homepage, documentation, readme, repository, license, max_upload_size) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) - RETURNING *" - )?; + RETURNING *", + )?; let rows = stmt.query( - &[ - &name, - &description, - &homepage, - &documentation, - &readme, - &repository, - &license, - &max_upload_size, - ] - )?; - let ret: Crate = Model::from_row( - &rows.iter() - .next() - .chain_error(|| internal("no crate returned"))? - ); + &[ + &name, + &description, + &homepage, + &documentation, + &readme, + &repository, + &license, + &max_upload_size, + ], + )?; + let ret: Crate = Model::from_row(&rows.iter().next().chain_error( + || internal("no crate returned"), + )?); conn.execute( - "INSERT INTO crate_owners + "INSERT INTO crate_owners (crate_id, owner_id, created_by, owner_kind) VALUES ($1, $2, $2, $3)", - &[&ret.id, &user_id, &(OwnerKind::User as i32)], - )?; + &[&ret.id, &user_id, &(OwnerKind::User as i32)], + )?; return Ok(ret); fn validate_url(url: Option<&str>, field: &str) -> CargoResult<()> { @@ -397,26 +399,27 @@ impl Crate { Some(s) => s, None => return Ok(()), }; - let url = Url::parse(url) - .map_err(|_| human(&format_args!("`{}` is not a valid url: `{}`", field, url)))?; + let url = Url::parse(url).map_err(|_| { + human(&format_args!("`{}` is not a valid url: `{}`", field, url)) + })?; match &url.scheme()[..] { "http" | "https" => {} s => { - return Err( - human( - &format_args!("`{}` has an invalid url \ - scheme: `{}`", field, s) - ) - ) + return Err(human(&format_args!( + "`{}` has an invalid url \ + scheme: `{}`", + field, + s + ))) } } if url.cannot_be_a_base() { - return Err( - human( - &format_args!("`{}` must have relative scheme \ - data: {}", field, url) - ) - ); + return Err(human(&format_args!( + "`{}` must have relative scheme \ + data: {}", + field, + url + ))); } Ok(()) } @@ -428,15 +431,14 @@ impl Crate { .map(license_exprs::validate_license_expr) .collect::, _>>() .map(|_| ()) - .map_err( - |e| { - human( - &format_args!("{}; see http://opensource.org/licenses \ + .map_err(|e| { + human(&format_args!( + "{}; see http://opensource.org/licenses \ for options, and http://spdx.org/licenses/ \ - for their identifiers", e) - ) - } - ) + for their identifiers", + e + )) + }) } } @@ -451,8 +453,9 @@ impl Crate { return false; } name.chars().next().unwrap().is_alphabetic() && - name.chars() - .all(|c| c.is_alphanumeric() || c == '_' || c == '-') && name.chars().all(|c| c.is_ascii()) + name.chars().all( + |c| c.is_alphanumeric() || c == '_' || c == '-', + ) && name.chars().all(|c| c.is_ascii()) } pub fn valid_feature_name(name: &str) -> bool { @@ -541,24 +544,22 @@ impl Crate { pub fn max_version_old(&self, conn: &GenericConnection) -> CargoResult { let stmt = conn.prepare( - "SELECT num FROM versions WHERE crate_id = $1 - AND yanked = 'f'" - )?; + "SELECT num FROM versions WHERE crate_id = $1 + AND yanked = 'f'", + )?; let rows = stmt.query(&[&self.id])?; - Ok( - Version::max( - rows.iter() - .map(|r| r.get::<_, String>("num")) - .map(|s| semver::Version::parse(&s).unwrap()) - ) - ) + Ok(Version::max( + rows.iter().map(|r| r.get::<_, String>("num")).map(|s| { + semver::Version::parse(&s).unwrap() + }), + )) } pub fn versions(&self, conn: &GenericConnection) -> CargoResult> { let stmt = conn.prepare( - "SELECT * FROM versions \ - WHERE crate_id = $1" - )?; + "SELECT * FROM versions \ + WHERE crate_id = $1", + )?; let rows = stmt.query(&[&self.id])?; let mut ret = rows.iter() .map(|r| Model::from_row(&r)) @@ -589,23 +590,23 @@ impl Crate { pub fn owners_old(&self, conn: &GenericConnection) -> CargoResult> { let stmt = conn.prepare( - "SELECT * FROM users + "SELECT * FROM users INNER JOIN crate_owners ON crate_owners.owner_id = users.id WHERE crate_owners.crate_id = $1 AND crate_owners.deleted = FALSE - AND crate_owners.owner_kind = $2" - )?; + AND crate_owners.owner_kind = $2", + )?; let user_rows = stmt.query(&[&self.id, &(OwnerKind::User as i32)])?; let stmt = conn.prepare( - "SELECT * FROM teams + "SELECT * FROM teams INNER JOIN crate_owners ON crate_owners.owner_id = teams.id WHERE crate_owners.crate_id = $1 AND crate_owners.deleted = FALSE - AND crate_owners.owner_kind = $2" - )?; + AND crate_owners.owner_kind = $2", + )?; let team_rows = stmt.query(&[&self.id, &(OwnerKind::Team as i32)])?; let mut owners = vec![]; @@ -621,12 +622,11 @@ impl Crate { if team.contains_user(app, req_user)? { Owner::Team(team) } else { - return Err( - human( - &format_args!("only members of {} can add it as \ - an owner", login) - ) - ); + return Err(human(&format_args!( + "only members of {} can add it as \ + an owner", + login + ))); } } Err(err) => { @@ -644,21 +644,19 @@ impl Crate { created_by: req_user.id, owner_kind: owner.kind() as i32, }; - diesel::insert( - &crate_owner.on_conflict( - crate_owners::table.primary_key(), - do_update().set(crate_owners::deleted.eq(false)), - ) - ) - .into(crate_owners::table) - .execute(conn)?; + diesel::insert(&crate_owner.on_conflict( + crate_owners::table.primary_key(), + do_update().set(crate_owners::deleted.eq(false)), + )).into(crate_owners::table) + .execute(conn)?; Ok(()) } pub fn owner_remove(&self, conn: &PgConnection, _req_user: &User, login: &str) -> CargoResult<()> { - let owner = Owner::find_by_login(conn, login) - .map_err(|_| human(&format_args!("could not find owner with login `{}`", login)))?; + let owner = Owner::find_by_login(conn, login).map_err(|_| { + human(&format_args!("could not find owner with login `{}`", login)) + })?; let target = crate_owners::table.find((self.id(), owner.id(), owner.kind() as i32)); diesel::update(target) .set(crate_owners::deleted.eq(true)) @@ -674,38 +672,40 @@ impl Crate { authors: &[String], ) -> CargoResult { if Version::find_by_num(conn, self.id, ver)?.is_some() { - return Err(human(&format_args!("crate version `{}` is already uploaded", ver))); + return Err(human( + &format_args!("crate version `{}` is already uploaded", ver), + )); } Version::insert(conn, self.id, ver, features, authors) } pub fn keywords(&self, conn: &GenericConnection) -> CargoResult> { let stmt = conn.prepare( - "SELECT keywords.* FROM keywords + "SELECT keywords.* FROM keywords LEFT JOIN crates_keywords ON keywords.id = crates_keywords.keyword_id - WHERE crates_keywords.crate_id = $1" - )?; + WHERE crates_keywords.crate_id = $1", + )?; let rows = stmt.query(&[&self.id])?; Ok(rows.iter().map(|r| Model::from_row(&r)).collect()) } pub fn categories(&self, conn: &GenericConnection) -> CargoResult> { let stmt = conn.prepare( - "SELECT categories.* FROM categories \ + "SELECT categories.* FROM categories \ LEFT JOIN crates_categories \ ON categories.id = \ crates_categories.category_id \ - WHERE crates_categories.crate_id = $1" - )?; + WHERE crates_categories.crate_id = $1", + )?; let rows = stmt.query(&[&self.id])?; Ok(rows.iter().map(|r| Model::from_row(&r)).collect()) } pub fn badges(&self, conn: &PgConnection) -> QueryResult> { - badges::table - .filter(badges::crate_id.eq(self.id)) - .load(conn) + badges::table.filter(badges::crate_id.eq(self.id)).load( + conn, + ) } /// Returns (dependency, dependent crate name, dependent crate downloads) @@ -758,7 +758,11 @@ pub fn index(req: &mut Request) -> CargoResult { let sort = params.get("sort").map(|s| &**s).unwrap_or("alpha"); let mut query = crates::table - .select((ALL_COLUMNS, sql::("COUNT(*) OVER ()"), sql::("false"))) + .select(( + ALL_COLUMNS, + sql::("COUNT(*) OVER ()"), + sql::("false"), + )) .limit(limit) .offset(offset) .into_boxed(); @@ -773,7 +777,11 @@ pub fn index(req: &mut Request) -> CargoResult { let q = plainto_tsquery(q_string); query = query.filter(q.matches(crates::textsearchable_index_col)); - query = query.select((ALL_COLUMNS, sql::("COUNT(*) OVER()"), crates::name.eq(q_string))); + query = query.select(( + ALL_COLUMNS, + sql::("COUNT(*) OVER()"), + crates::name.eq(q_string), + )); let perfect_match = crates::name.eq(q_string).desc(); if sort == "downloads" { query = query.order((perfect_match, crates::downloads.desc())); @@ -789,12 +797,11 @@ pub fn index(req: &mut Request) -> CargoResult { crates_categories::table .select(crates_categories::crate_id) .inner_join(categories::table) - .filter( - categories::slug - .eq(cat) - .or(categories::slug.like(format!("{}::%", cat))) - ) - ) + .filter(categories::slug.eq(cat).or(categories::slug.like(format!( + "{}::%", + cat + )))), + ), ); } @@ -804,12 +811,19 @@ pub fn index(req: &mut Request) -> CargoResult { crates_keywords::table .select(crates_keywords::crate_id) .inner_join(keywords::table) - .filter(::lower(keywords::keyword).eq(::lower(kw))) - ) + .filter(::lower(keywords::keyword).eq(::lower(kw))), + ), ); } else if let Some(letter) = params.get("letter") { - let pattern = format!("{}%", letter.chars().next().unwrap() - .to_lowercase().collect::()); + let pattern = format!( + "{}%", + letter + .chars() + .next() + .unwrap() + .to_lowercase() + .collect::() + ); query = query.filter(canon_crate_name(crates::name).like(pattern)); } else if let Some(user_id) = params.get("user_id").and_then(|s| s.parse::().ok()) { query = query.filter( @@ -817,17 +831,15 @@ pub fn index(req: &mut Request) -> CargoResult { crate_owners::table .select(crate_owners::crate_id) .filter(crate_owners::owner_id.eq(user_id)) - .filter(crate_owners::owner_kind.eq(OwnerKind::User as i32)) - ) + .filter(crate_owners::owner_kind.eq(OwnerKind::User as i32)), + ), ); } else if params.get("following").is_some() { - query = query.filter( - crates::id.eq_any( - follows::table - .select(follows::crate_id) - .filter(follows::user_id.eq(req.user()?.id)) - ) - ); + query = query.filter(crates::id.eq_any( + follows::table.select(follows::crate_id).filter( + follows::user_id.eq(req.user()?.id), + ), + )); } let data = query.load::<(Crate, i64, bool)>(&*conn)?; @@ -846,16 +858,18 @@ pub fn index(req: &mut Request) -> CargoResult { let crates = versions .zip(crates) .zip(perfect_matches) - .map( - |((max_version, krate), perfect_match)| { - // FIXME: If we add crate_id to the Badge enum we can eliminate - // this N+1 - let badges = badges::table - .filter(badges::crate_id.eq(krate.id)) - .load::(&*conn)?; - Ok(krate.minimal_encodable(max_version, Some(badges), perfect_match)) - } - ) + .map(|((max_version, krate), perfect_match)| { + // FIXME: If we add crate_id to the Badge enum we can eliminate + // this N+1 + let badges = badges::table + .filter(badges::crate_id.eq(krate.id)) + .load::(&*conn)?; + Ok(krate.minimal_encodable( + max_version, + Some(badges), + perfect_match, + )) + }) .collect::>()?; #[derive(RustcEncodable)] @@ -868,14 +882,10 @@ pub fn index(req: &mut Request) -> CargoResult { total: i64, } - Ok( - req.json( - &R { - crates: crates, - meta: Meta { total: total }, - } - ) - ) + Ok(req.json(&R { + crates: crates, + meta: Meta { total: total }, + })) } /// Handles the `GET /summary` route. @@ -896,7 +906,9 @@ pub fn summary(req: &mut Request) -> CargoResult { .into_iter() .map(|versions| Version::max(versions.into_iter().map(|v| v.num))) .zip(krates) - .map(|(max_version, krate)| Ok(krate.minimal_encodable(max_version, None, false))) + .map(|(max_version, krate)| { + Ok(krate.minimal_encodable(max_version, None, false)) + }) .collect() }; @@ -940,19 +952,15 @@ pub fn summary(req: &mut Request) -> CargoResult { popular_keywords: Vec, popular_categories: Vec, } - Ok( - req.json( - &R { - num_downloads: num_downloads, - num_crates: num_crates, - new_crates: encode_crates(new_crates)?, - most_downloaded: encode_crates(most_downloaded)?, - just_updated: encode_crates(just_updated)?, - popular_keywords: popular_keywords, - popular_categories: popular_categories, - } - ) - ) + Ok(req.json(&R { + num_downloads: num_downloads, + num_crates: num_crates, + new_crates: encode_crates(new_crates)?, + most_downloaded: encode_crates(most_downloaded)?, + just_updated: encode_crates(just_updated)?, + popular_keywords: popular_keywords, + popular_categories: popular_categories, + })) } /// Handles the `GET /crates/:crate_id` route. @@ -974,9 +982,9 @@ pub fn show(req: &mut Request) -> CargoResult { .select(categories::all_columns) .load(&*conn)?; - let badges = badges::table - .filter(badges::crate_id.eq(krate.id)) - .load(&*conn)?; + let badges = badges::table.filter(badges::crate_id.eq(krate.id)).load( + &*conn, + )?; let max_version = krate.max_version(&conn)?; #[derive(RustcEncodable)] @@ -987,26 +995,22 @@ pub fn show(req: &mut Request) -> CargoResult { categories: Vec, } Ok( - req.json( - &R { - krate: krate - .clone() - .encodable( - max_version, - Some(ids), - Some(&kws), - Some(&cats), - Some(badges), - false, - ), - versions: versions - .into_iter() - .map(|v| v.encodable(&krate.name)) - .collect(), - keywords: kws.into_iter().map(|k| k.encodable()).collect(), - categories: cats.into_iter().map(|k| k.encodable()).collect(), - } - ) + req.json(&R { + krate: krate.clone().encodable( + max_version, + Some(ids), + Some(&kws), + Some(&cats), + Some(badges), + false, + ), + versions: versions + .into_iter() + .map(|v| v.encodable(&krate.name)) + .collect(), + keywords: kws.into_iter().map(|k| k.encodable()).collect(), + categories: cats.into_iter().map(|k| k.encodable()).collect(), + }), ) } @@ -1020,7 +1024,12 @@ pub fn new(req: &mut Request) -> CargoResult { let features = new_crate .features .iter() - .map(|(k, v)| (k[..].to_string(), v.iter().map(|v| v[..].to_string()).collect())) + .map(|(k, v)| { + ( + k[..].to_string(), + v.iter().map(|v| v[..].to_string()).collect(), + ) + }) .collect::>>(); let keywords = new_crate .keywords @@ -1032,110 +1041,112 @@ pub fn new(req: &mut Request) -> CargoResult { let categories: Vec<_> = categories.iter().map(|k| &**k).collect(); let conn = req.db_conn()?; - conn.transaction( - || { - // Persist the new crate, if it doesn't already exist - let persist = NewCrate { - name: name, - description: new_crate.description.as_ref().map(|s| &**s), - homepage: new_crate.homepage.as_ref().map(|s| &**s), - documentation: new_crate.documentation.as_ref().map(|s| &**s), - readme: new_crate.readme.as_ref().map(|s| &**s), - repository: new_crate.repository.as_ref().map(|s| &**s), - license: new_crate.license.as_ref().map(|s| &**s), - max_upload_size: None, - }; - let license_file = new_crate.license_file.as_ref().map(|s| &**s); - let krate = persist.create_or_update(&conn, license_file, user.id)?; - - let owners = krate.owners(&conn)?; - if rights(req.app(), &owners, &user)? < Rights::Publish { - return Err( - human( - "crate name has already been claimed by \ - another user" - ) - ); - } + conn.transaction(|| { + // Persist the new crate, if it doesn't already exist + let persist = NewCrate { + name: name, + description: new_crate.description.as_ref().map(|s| &**s), + homepage: new_crate.homepage.as_ref().map(|s| &**s), + documentation: new_crate.documentation.as_ref().map(|s| &**s), + readme: new_crate.readme.as_ref().map(|s| &**s), + repository: new_crate.repository.as_ref().map(|s| &**s), + license: new_crate.license.as_ref().map(|s| &**s), + max_upload_size: None, + }; + let license_file = new_crate.license_file.as_ref().map(|s| &**s); + let krate = persist.create_or_update(&conn, license_file, user.id)?; + + let owners = krate.owners(&conn)?; + if rights(req.app(), &owners, &user)? < Rights::Publish { + return Err(human( + "crate name has already been claimed by \ + another user", + )); + } - if krate.name != name { - return Err(human(&format_args!("crate was previously named `{}`", krate.name))); - } + if krate.name != name { + return Err(human( + &format_args!("crate was previously named `{}`", krate.name), + )); + } - let length = req.content_length() - .chain_error(|| human("missing header: Content-Length"))?; - let max = krate - .max_upload_size - .map(|m| m as u64) - .unwrap_or(app.config.max_upload_size); - if length > max { - return Err(human(&format_args!("max upload size is: {}", max))); - } + let length = req.content_length().chain_error(|| { + human("missing header: Content-Length") + })?; + let max = krate.max_upload_size.map(|m| m as u64).unwrap_or( + app.config + .max_upload_size, + ); + if length > max { + return Err(human(&format_args!("max upload size is: {}", max))); + } - // Persist the new version of this crate - let version = NewVersion::new(krate.id, vers, &features)? - .save(&conn, &new_crate.authors)?; - - // Link this new version to all dependencies - let git_deps = dependency::add_dependencies(&conn, &new_crate.deps, version.id)?; - - // Update all keywords for this crate - Keyword::update_crate(&conn, &krate, &keywords)?; - - // Update all categories for this crate, collecting any invalid categories - // in order to be able to warn about them - let ignored_invalid_categories = Category::update_crate(&conn, &krate, &categories)?; - - // Update all badges for this crate, collecting any invalid badges in - // order to be able to warn about them - let ignored_invalid_badges = Badge::update_crate(&conn, &krate, new_crate.badges.as_ref())?; - let max_version = krate.max_version(&conn)?; - - // Upload the crate, return way to delete the crate from the server - // If the git commands fail below, we shouldn't keep the crate on the - // server. - let (cksum, mut bomb) = app.config.uploader.upload(req, &krate, max, vers)?; - - // Register this crate in our local git repo. - let git_crate = git::Crate { - name: name.to_string(), - vers: vers.to_string(), - cksum: cksum.to_hex(), - features: features, - deps: git_deps, - yanked: Some(false), - }; - git::add_crate(&**req.app(), &git_crate) - .chain_error(|| internal(&format_args!("could not add crate `{}` to the git repo", name)))?; + // Persist the new version of this crate + let version = NewVersion::new(krate.id, vers, &features)?.save( + &conn, + &new_crate + .authors, + )?; + + // Link this new version to all dependencies + let git_deps = dependency::add_dependencies(&conn, &new_crate.deps, version.id)?; + + // Update all keywords for this crate + Keyword::update_crate(&conn, &krate, &keywords)?; + + // Update all categories for this crate, collecting any invalid categories + // in order to be able to warn about them + let ignored_invalid_categories = Category::update_crate(&conn, &krate, &categories)?; + + // Update all badges for this crate, collecting any invalid badges in + // order to be able to warn about them + let ignored_invalid_badges = Badge::update_crate(&conn, &krate, new_crate.badges.as_ref())?; + let max_version = krate.max_version(&conn)?; + + // Upload the crate, return way to delete the crate from the server + // If the git commands fail below, we shouldn't keep the crate on the + // server. + let (cksum, mut bomb) = app.config.uploader.upload(req, &krate, max, vers)?; + + // Register this crate in our local git repo. + let git_crate = git::Crate { + name: name.to_string(), + vers: vers.to_string(), + cksum: cksum.to_hex(), + features: features, + deps: git_deps, + yanked: Some(false), + }; + git::add_crate(&**req.app(), &git_crate).chain_error(|| { + internal(&format_args!( + "could not add crate `{}` to the git repo", + name + )) + })?; - // Now that we've come this far, we're committed! - bomb.path = None; + // Now that we've come this far, we're committed! + bomb.path = None; - #[derive(RustcEncodable)] - struct Warnings<'a> { - invalid_categories: Vec<&'a str>, - invalid_badges: Vec<&'a str>, - } - let warnings = Warnings { - invalid_categories: ignored_invalid_categories, - invalid_badges: ignored_invalid_badges, - }; + #[derive(RustcEncodable)] + struct Warnings<'a> { + invalid_categories: Vec<&'a str>, + invalid_badges: Vec<&'a str>, + } + let warnings = Warnings { + invalid_categories: ignored_invalid_categories, + invalid_badges: ignored_invalid_badges, + }; - #[derive(RustcEncodable)] - struct R<'a> { - krate: EncodableCrate, - warnings: Warnings<'a>, - } - Ok( - req.json( - &R { - krate: krate.minimal_encodable(max_version, None, false), - warnings: warnings, - } - ) - ) + #[derive(RustcEncodable)] + struct R<'a> { + krate: EncodableCrate, + warnings: Warnings<'a>, } - ) + Ok(req.json(&R { + krate: krate.minimal_encodable(max_version, None, false), + warnings: warnings, + })) + }) } fn parse_new_headers(req: &mut Request) -> CargoResult<(upload::NewCrate, User)> { @@ -1147,10 +1158,12 @@ fn parse_new_headers(req: &mut Request) -> CargoResult<(upload::NewCrate, User)> } let mut json = vec![0; amt as usize]; read_fill(req.body(), &mut json)?; - let json = String::from_utf8(json) - .map_err(|_| human("json body was not valid utf-8"))?; - let new: upload::NewCrate = json::decode(&json) - .map_err(|e| human(&format_args!("invalid upload request: {:?}", e)))?; + let json = String::from_utf8(json).map_err(|_| { + human("json body was not valid utf-8") + })?; + let new: upload::NewCrate = json::decode(&json).map_err(|e| { + human(&format_args!("invalid upload request: {:?}", e)) + })?; // Make sure required fields are provided fn empty(s: Option<&String>) -> bool { @@ -1168,13 +1181,12 @@ fn parse_new_headers(req: &mut Request) -> CargoResult<(upload::NewCrate, User)> missing.push("authors"); } if !missing.is_empty() { - return Err( - human( - &format_args!("missing or empty metadata fields: {}. Please \ + return Err(human(&format_args!( + "missing or empty metadata fields: {}. Please \ see http://doc.crates.io/manifest.html#package-metadata for \ - how to upload metadata", missing.join(", ")) - ) - ); + how to upload metadata", + missing.join(", ") + ))); } let user = req.user()?; @@ -1219,7 +1231,9 @@ fn increment_download_counts(req: &Request, crate_name: &str, version: &str) -> let conn = req.db_conn()?; let version_id = versions .select(id) - .filter(crate_id.eq_any(Crate::by_name(crate_name).select(crates::id))) + .filter(crate_id.eq_any( + Crate::by_name(crate_name).select(crates::id), + )) .filter(num.eq(version)) .first(&*conn)?; @@ -1250,7 +1264,10 @@ pub fn downloads(req: &mut Request) -> CargoResult { let sum_downloads = sql::("SUM(version_downloads.downloads)"); let extra = VersionDownload::belonging_to(rest) - .select((to_char(version_downloads::date, "YYYY-MM-DD"), sum_downloads)) + .select(( + to_char(version_downloads::date, "YYYY-MM-DD"), + sum_downloads, + )) .filter(version_downloads::date.gt(date(now - 90.days()))) .group_by(version_downloads::date) .order(version_downloads::date.asc()) @@ -1271,20 +1288,16 @@ pub fn downloads(req: &mut Request) -> CargoResult { extra_downloads: Vec, } let meta = Meta { extra_downloads: extra }; - Ok( - req.json( - &R { - version_downloads: downloads, - meta: meta, - } - ) - ) + Ok(req.json(&R { + version_downloads: downloads, + meta: meta, + })) } #[derive(Insertable, Queryable, Identifiable, Associations)] #[belongs_to(User)] #[primary_key(user_id, crate_id)] -#[table_name="follows"] +#[table_name = "follows"] pub struct Follow { user_id: i32, crate_id: i32, @@ -1295,12 +1308,10 @@ fn follow_target(req: &mut Request) -> CargoResult { let conn = req.db_conn()?; let crate_name = &req.params()["crate_id"]; let crate_id = Crate::by_name(crate_name).select(crates::id).first(&*conn)?; - Ok( - Follow { - user_id: user.id, - crate_id: crate_id, - } - ) + Ok(Follow { + user_id: user.id, + crate_id: crate_id, + }) } /// Handles the `PUT /crates/:crate_id/follow` route. @@ -1397,8 +1408,9 @@ fn modify_owners(req: &mut Request, add: bool) -> CargoResult { req.body().read_to_string(&mut body)?; let user = req.user()?; let conn = req.db_conn()?; - let krate = Crate::by_name(&req.params()["crate_id"]) - .first::(&*conn)?; + let krate = Crate::by_name(&req.params()["crate_id"]).first::( + &*conn, + )?; let owners = krate.owners(&conn)?; match rights(req.app(), &owners, user)? { @@ -1418,13 +1430,13 @@ fn modify_owners(req: &mut Request, add: bool) -> CargoResult { owners: Option>, } - let request: Request = json::decode(&body) - .map_err(|_| human("invalid json request"))?; + let request: Request = json::decode(&body).map_err( + |_| human("invalid json request"), + )?; - let logins = request - .owners - .or(request.users) - .ok_or_else(|| human("invalid json request"))?; + let logins = request.owners.or(request.users).ok_or_else(|| { + human("invalid json request") + })?; for login in &logins { if add { @@ -1470,14 +1482,10 @@ pub fn reverse_dependencies(req: &mut Request) -> CargoResult { struct Meta { total: i64, } - Ok( - req.json( - &R { - dependencies: rev_deps, - meta: Meta { total: total }, - } - ) - ) + Ok(req.json(&R { + dependencies: rev_deps, + meta: Meta { total: total }, + })) } use diesel::types::{Text, Date}; diff --git a/src/lib.rs b/src/lib.rs index a2ebbe6fc8b..71cc750fb3e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -183,7 +183,10 @@ pub fn middleware(app: Arc) -> MiddlewareBuilder { m.around(util::Head::default()); m.add(conduit_conditional_get::ConditionalGet); m.add(conduit_cookie::Middleware::new(app.session_key.as_bytes())); - m.add(conduit_cookie::SessionMiddleware::new("cargo_session", env == Env::Production)); + m.add(conduit_cookie::SessionMiddleware::new( + "cargo_session", + env == Env::Production, + )); m.add(app::AppMiddleware::new(app)); if env != Env::Test { m.add(db::TransactionMiddleware); @@ -211,20 +214,14 @@ pub fn middleware(app: Arc) -> MiddlewareBuilder { } Ok(()) } - fn after( - &self, - _req: &mut conduit::Request, - res: Result>, - ) -> Result> { - res.map( - |res| { - println!(" <- {:?}", res.status); - for (k, v) in &res.headers { - println!(" <- {} {:?}", k, v); - } - res + fn after(&self, _req: &mut conduit::Request, res: Result>) -> Result> { + res.map(|res| { + println!(" <- {:?}", res.status); + for (k, v) in &res.headers { + println!(" <- {} {:?}", k, v); } - ) + res + }) } } } diff --git a/src/model.rs b/src/model.rs index 07381044776..fc0ed056f92 100644 --- a/src/model.rs +++ b/src/model.rs @@ -9,8 +9,10 @@ pub trait Model: Sized { fn table_name(_: Option) -> &'static str; fn find(conn: &GenericConnection, id: i32) -> CargoResult { - let sql = format!("SELECT * FROM {} WHERE id = $1", - Model::table_name(None::)); + let sql = format!( + "SELECT * FROM {} WHERE id = $1", + Model::table_name(None::) + ); let stmt = conn.prepare(&sql)?; let rows = stmt.query(&[&id])?; let row = rows.into_iter().next().chain_error(|| NotFound)?; diff --git a/src/owner.rs b/src/owner.rs index 898e8fb0c49..8a389aa8af3 100644 --- a/src/owner.rs +++ b/src/owner.rs @@ -11,9 +11,9 @@ use {Model, User, Crate}; #[derive(Insertable, Associations, Identifiable)] #[belongs_to(Crate)] -#[belongs_to(User, foreign_key="owner_id")] -#[belongs_to(Team, foreign_key="owner_id")] -#[table_name="crate_owners"] +#[belongs_to(User, foreign_key = "owner_id")] +#[belongs_to(Team, foreign_key = "owner_id")] +#[table_name = "crate_owners"] #[primary_key(crate_id, owner_id, owner_kind)] pub struct CrateOwner { pub crate_id: i32, @@ -82,25 +82,19 @@ impl Team { "github" => { // Ok to unwrap since we know one ":" is contained let org = chunks.next().unwrap(); - let team = chunks - .next() - .ok_or_else( - || { - human( - "missing github team argument; \ - format is github:org:team" - ) - } - )?; + let team = chunks.next().ok_or_else(|| { + human( + "missing github team argument; \ + format is github:org:team", + ) + })?; Team::create_github_team(app, conn, login, org, team, req_user) } _ => { - Err( - human( - "unknown organization handler, \ - only 'github:org:team' is supported" - ) - ) + Err(human( + "unknown organization handler, \ + only 'github:org:team' is supported", + )) } } } @@ -108,14 +102,7 @@ impl Team { /// Tries to create a Github Team from scratch. Assumes `org` and `team` are /// correctly parsed out of the full `name`. `name` is passed as a /// convenience to avoid rebuilding it. - pub fn create_github_team( - app: &App, - conn: &PgConnection, - login: &str, - org_name: &str, - team_name: &str, - req_user: &User, - ) -> CargoResult { + pub fn create_github_team(app: &App, conn: &PgConnection, login: &str, org_name: &str, team_name: &str, req_user: &User) -> CargoResult { // GET orgs/:org/teams // check that `team` is the `slug` in results, and grab its data @@ -128,12 +115,11 @@ impl Team { } if let Some(c) = org_name.chars().find(whitelist) { - return Err( - human( - &format_args!("organization cannot contain special \ - characters like {}", c) - ) - ); + return Err(human(&format_args!( + "organization cannot contain special \ + characters like {}", + c + ))); } #[derive(RustcDecodable)] @@ -153,14 +139,13 @@ impl Team { let team = teams .into_iter() .find(|team| team.slug == team_name) - .ok_or_else( - || { - human( - &format_args!("could not find the github team {}/{}", - org_name, team_name) - ) - } - )?; + .ok_or_else(|| { + human(&format_args!( + "could not find the github team {}/{}", + org_name, + team_name + )) + })?; if !team_with_gh_id_contains_user(app, team.id, req_user)? { return Err(human("only members of a team can add it as an owner")); @@ -182,7 +167,7 @@ impl Team { use diesel::pg::upsert::*; #[derive(Insertable, AsChangeset)] - #[table_name="teams"] + #[table_name = "teams"] struct NewTeam<'a> { login: &'a str, github_id: i32, @@ -196,8 +181,10 @@ impl Team { avatar: avatar, }; - diesel::insert(&new_team.on_conflict(teams::github_id, do_update().set(&new_team))) - .into(teams::table) + diesel::insert(&new_team.on_conflict( + teams::github_id, + do_update().set(&new_team), + )).into(teams::table) .get_result(conn) .map_err(Into::into) } @@ -220,8 +207,7 @@ fn team_with_gh_id_contains_user(app: &App, github_id: i32, user: &User) -> Carg state: String, } - let url = format!("/teams/{}/memberships/{}", - &github_id, &user.gh_login); + let url = format!("/teams/{}/memberships/{}", &github_id, &user.gh_login); let token = http::token(user.gh_access_token.clone()); let (mut handle, resp) = http::github(app, &url, &token)?; @@ -263,13 +249,17 @@ impl Owner { .filter(teams::login.eq(name)) .first(conn) .map(Owner::Team) - .map_err(|_| human(&format_args!("could not find team with name {}", name))) + .map_err(|_| { + human(&format_args!("could not find team with name {}", name)) + }) } else { users::table .filter(users::gh_login.eq(name)) .first(conn) .map(Owner::User) - .map_err(|_| human(&format_args!("could not find user with login `{}`", name))) + .map_err(|_| { + human(&format_args!("could not find user with login `{}`", name)) + }) } } @@ -325,8 +315,11 @@ impl Owner { let url = { let mut parts = login.split(':'); parts.next(); // discard github - format!("https://github.com/orgs/{}/teams/{}", - parts.next().unwrap(), parts.next().unwrap()) + format!( + "https://github.com/orgs/{}/teams/{}", + parts.next().unwrap(), + parts.next().unwrap() + ) }; EncodableOwner { id: id, diff --git a/src/tests/all.rs b/src/tests/all.rs index ad411786b46..6a3a4c3b8b5 100755 --- a/src/tests/all.rs +++ b/src/tests/all.rs @@ -162,9 +162,9 @@ fn json(r: &mut conduit::Response) -> T { let j = fixup(j); let s = j.to_string(); return match json::decode(&s) { - Ok(t) => t, - Err(e) => panic!("failed to decode: {:?}\n{}", e, s), - }; + Ok(t) => t, + Err(e) => panic!("failed to decode: {:?}\n{}", e, s), + }; fn fixup(json: Json) -> Json { @@ -173,13 +173,11 @@ fn json(r: &mut conduit::Response) -> T { Json::Object( object .into_iter() - .map( - |(k, v)| { - let k = if k == "crate" { "krate".to_string() } else { k }; - (k, fixup(v)) - } - ) - .collect() + .map(|(k, v)| { + let k = if k == "crate" { "krate".to_string() } else { k }; + (k, fixup(v)) + }) + .collect(), ) } Json::Array(list) => Json::Array(list.into_iter().map(fixup).collect()), @@ -271,11 +269,9 @@ impl<'a> CrateBuilder<'a> { } fn version(mut self, version: &str) -> Self { - let version = semver::Version::parse(version).unwrap_or_else( - |e| { - panic!("The version {} is not valid: {}", version, e); - } - ); + let version = semver::Version::parse(version).unwrap_or_else(|e| { + panic!("The version {} is not valid: {}", version, e); + }); self.versions.push(version); self } @@ -288,8 +284,11 @@ impl<'a> CrateBuilder<'a> { fn build(mut self, connection: &PgConnection) -> CargoResult { use diesel::update; - let mut krate = self.krate - .create_or_update(connection, self.license_file, self.owner_id)?; + let mut krate = self.krate.create_or_update( + connection, + self.license_file, + self.owner_id, + )?; // Since we are using `NewCrate`, we can't set all the // crate properties in a single DB call. @@ -299,8 +298,9 @@ impl<'a> CrateBuilder<'a> { } if self.versions.is_empty() { - self.versions - .push("0.99.0".parse().expect("invalid version number")); + self.versions.push("0.99.0".parse().expect( + "invalid version number", + )); } for version_num in &self.versions { @@ -317,12 +317,9 @@ impl<'a> CrateBuilder<'a> { fn expect_build(self, connection: &PgConnection) -> Crate { let name = self.krate.name; - self.build(connection) - .unwrap_or_else( - |e| { - panic!("Unable to create crate {}: {:?}", name, e); - } - ) + self.build(connection).unwrap_or_else(|e| { + panic!("Unable to create crate {}: {:?}", name, e); + }) } } @@ -357,8 +354,7 @@ fn mock_user(req: &mut Request, u: User) -> User { u.name.as_ref().map(|s| &s[..]), u.gh_avatar.as_ref().map(|s| &s[..]), &u.gh_access_token, - ) - .unwrap(); + ).unwrap(); sign_in_as(req, &u); return u; } @@ -391,8 +387,7 @@ fn mock_crate_vers(req: &mut Request, krate: Crate, v: &semver::Version) -> (Cra &krate.license, &None, krate.max_upload_size, - ) - .unwrap(); + ).unwrap(); let v = krate.add_version(req.tx().unwrap(), v, &HashMap::new(), &[]); (krate, v.unwrap()) } @@ -425,8 +420,7 @@ fn mock_dep(req: &mut Request, version: &Version, krate: &Crate, target: Option< true, &[], &target.map(|s| s.to_string()), - ) - .unwrap() + ).unwrap() } fn new_category<'a>(category: &'a str, slug: &'a str) -> NewCategory<'a> { @@ -440,12 +434,11 @@ fn new_category<'a>(category: &'a str, slug: &'a str) -> NewCategory<'a> { fn mock_category(req: &mut Request, name: &str, slug: &str) -> Category { let conn = req.tx().unwrap(); let stmt = conn.prepare( - " \ + " \ INSERT INTO categories (category, slug) \ VALUES ($1, $2) \ - RETURNING *" - ) - .unwrap(); + RETURNING *", + ).unwrap(); let rows = stmt.query(&[&name, &slug]).unwrap(); Model::from_row(&rows.iter().next().unwrap()) } @@ -471,25 +464,53 @@ fn new_req(app: Arc, krate: &str, version: &str) -> MockRequest { fn new_req_full(app: Arc, krate: Crate, version: &str, deps: Vec) -> MockRequest { let mut req = ::req(app, Method::Put, "/api/v1/crates/new"); - req.with_body(&new_req_body(krate, version, deps, Vec::new(), Vec::new(), HashMap::new())); + req.with_body(&new_req_body( + krate, + version, + deps, + Vec::new(), + Vec::new(), + HashMap::new(), + )); return req; } fn new_req_with_keywords(app: Arc, krate: Crate, version: &str, kws: Vec) -> MockRequest { let mut req = ::req(app, Method::Put, "/api/v1/crates/new"); - req.with_body(&new_req_body(krate, version, Vec::new(), kws, Vec::new(), HashMap::new())); + req.with_body(&new_req_body( + krate, + version, + Vec::new(), + kws, + Vec::new(), + HashMap::new(), + )); return req; } fn new_req_with_categories(app: Arc, krate: Crate, version: &str, cats: Vec) -> MockRequest { let mut req = ::req(app, Method::Put, "/api/v1/crates/new"); - req.with_body(&new_req_body(krate, version, Vec::new(), Vec::new(), cats, HashMap::new())); + req.with_body(&new_req_body( + krate, + version, + Vec::new(), + Vec::new(), + cats, + HashMap::new(), + )); return req; } fn new_req_with_badges(app: Arc, krate: Crate, version: &str, badges: HashMap>) -> MockRequest { let mut req = ::req(app, Method::Put, "/api/v1/crates/new"); - req.with_body(&new_req_body(krate, version, Vec::new(), Vec::new(), Vec::new(), badges)); + req.with_body(&new_req_body( + krate, + version, + Vec::new(), + Vec::new(), + Vec::new(), + badges, + )); return req; } @@ -545,9 +566,8 @@ fn new_crate_to_body(new_crate: &u::NewCrate, krate: &[u8]) -> Vec { (json.len() >> 8) as u8, (json.len() >> 16) as u8, (json.len() >> 24) as u8, - ] - .iter() - .cloned() + ].iter() + .cloned(), ); body.extend(json.as_bytes().iter().cloned()); body.extend( @@ -556,7 +576,7 @@ fn new_crate_to_body(new_crate: &u::NewCrate, krate: &[u8]) -> Vec { (krate.len() >> 8) as u8, (krate.len() >> 16) as u8, (krate.len() >> 24) as u8, - ] + ], ); body.extend(krate); body diff --git a/src/tests/badge.rs b/src/tests/badge.rs index e97b812a166..86a06ee8f31 100644 --- a/src/tests/badge.rs +++ b/src/tests/badge.rs @@ -375,9 +375,9 @@ fn isitmaintained_open_issues_required_keys() { let mut badges = HashMap::new(); // Repository is a required key - test_badges - .isitmaintained_open_issues_attributes - .remove("repository"); + test_badges.isitmaintained_open_issues_attributes.remove( + "repository", + ); badges.insert( String::from("isitmaintained_open_issues"), test_badges.isitmaintained_open_issues_attributes, diff --git a/src/tests/category.rs b/src/tests/category.rs index b251448a3eb..511b0b2c131 100644 --- a/src/tests/category.rs +++ b/src/tests/category.rs @@ -107,8 +107,7 @@ fn update_crate() { req.tx().unwrap(), &krate, &["cat1".to_string(), "category-2".to_string()], - ) - .unwrap(); + ).unwrap(); assert_eq!(cnt(&mut req, "cat1"), 1); assert_eq!(cnt(&mut req, "category-2"), 1); @@ -122,8 +121,7 @@ fn update_crate() { req.tx().unwrap(), &krate, &["cat1".to_string(), "catnope".to_string()], - ) - .unwrap(); + ).unwrap(); assert_eq!(invalid_categories, vec!["catnope".to_string()]); assert_eq!(cnt(&mut req, "cat1"), 1); assert_eq!(cnt(&mut req, "category-2"), 0); @@ -147,8 +145,7 @@ fn update_crate() { req.tx().unwrap(), &krate, &["cat1".to_string(), "cat1::bar".to_string()], - ) - .unwrap(); + ).unwrap(); assert_eq!(cnt(&mut req, "cat1"), 1); assert_eq!(cnt(&mut req, "cat1::bar"), 1); assert_eq!(cnt(&mut req, "category-2"), 0); diff --git a/src/tests/git.rs b/src/tests/git.rs index bd2309fd66d..3b26cd18c2e 100644 --- a/src/tests/git.rs +++ b/src/tests/git.rs @@ -8,10 +8,11 @@ use git2; use url::Url; fn root() -> PathBuf { - env::current_dir() - .unwrap() - .join("tmp") - .join(thread::current().name().unwrap()) + env::current_dir().unwrap().join("tmp").join( + thread::current() + .name() + .unwrap(), + ) } pub fn checkout() -> PathBuf { @@ -26,7 +27,9 @@ pub fn init() { let _ = fs::remove_dir_all(&checkout()); let _ = fs::remove_dir_all(&bare()); - INIT.call_once(|| { fs::create_dir_all(root().parent().unwrap()).unwrap(); }); + INIT.call_once(|| { + fs::create_dir_all(root().parent().unwrap()).unwrap(); + }); // Prepare a bare remote repo { diff --git a/src/tests/krate.rs b/src/tests/krate.rs index ceb2aa27cff..7c8e94233ca 100644 --- a/src/tests/krate.rs +++ b/src/tests/krate.rs @@ -229,7 +229,9 @@ fn exact_match_first_on_queries() { .expect_build(&conn); ::CrateBuilder::new("baz_exact", user.id) - .description("foo_exact bar_exact foo_exact bar_exact foo_exact bar_exact") + .description( + "foo_exact bar_exact foo_exact bar_exact foo_exact bar_exact", + ) .expect_build(&conn); ::CrateBuilder::new("other_exact", user.id) @@ -280,7 +282,9 @@ fn exact_match_on_queries_with_sort() { .expect_build(&conn); ::CrateBuilder::new("baz_sort", user.id) - .description("foo_sort bar_sort foo_sort bar_sort foo_sort bar_sort const") + .description( + "foo_sort bar_sort foo_sort bar_sort foo_sort bar_sort const", + ) .downloads(100000) .expect_build(&conn); @@ -450,11 +454,9 @@ fn new_krate_with_reserved_name() { let mut req = ::new_req(app, name, "1.0.0"); ::mock_user(&mut req, ::user("foo")); let json = bad_resp!(middle.call(&mut req)); - assert!( - json.errors[0] - .detail - .contains("cannot upload a crate with a reserved name") - ); + assert!(json.errors[0].detail.contains( + "cannot upload a crate with a reserved name", + )); } test_bad_name("std"); @@ -661,7 +663,7 @@ fn new_crate_owner() { middle.call( req.with_path("/api/v1/crates/foo_owner/owners") .with_method(Method::Put) - .with_body(body.as_bytes()) + .with_body(body.as_bytes()), ) ); assert!(::json::(&mut response).ok); @@ -669,7 +671,7 @@ fn new_crate_owner() { middle.call( req.with_path("/api/v1/crates/foo_owner/owners") .with_method(Method::Put) - .with_body(body.as_bytes()) + .with_body(body.as_bytes()), ) ); @@ -679,7 +681,7 @@ fn new_crate_owner() { middle.call( req.with_path("/api/v1/crates") .with_method(Method::Get) - .with_query(&query) + .with_query(&query), ) ); assert_eq!(::json::(&mut response).crates.len(), 1); @@ -691,7 +693,7 @@ fn new_crate_owner() { middle.call( req.with_path("/api/v1/crates/new") .with_method(Method::Put) - .with_body(&body) + .with_body(&body), ) ); ::json::(&mut response); @@ -841,7 +843,7 @@ fn new_krate_git_upload_appends() { .unwrap() .write_all( br#"{"name":"FPP","vers":"0.0.1","deps":[],"features":{},"cksum":"3j3"} -"# +"#, ) .unwrap(); @@ -903,11 +905,9 @@ fn new_krate_dependency_missing() { ::sign_in(&mut req, &app); let mut response = ok_resp!(middle.call(&mut req)); let json = ::json::<::Bad>(&mut response); - assert!( - json.errors[0] - .detail - .contains("no known crate named `bar_missing`") - ); + assert!(json.errors[0].detail.contains( + "no known crate named `bar_missing`", + )); } #[test] @@ -960,12 +960,16 @@ fn download() { let yesterday = now_utc() + Duration::days(-1); req.with_path("/api/v1/crates/FOO_DOWNLOAD/1.0.0/downloads"); - req.with_query(&("before_date=".to_string() + &strftime("%Y-%m-%d", &yesterday).unwrap())); + req.with_query( + &("before_date=".to_string() + &strftime("%Y-%m-%d", &yesterday).unwrap()), + ); let mut resp = ok_resp!(middle.call(&mut req)); let downloads = ::json::(&mut resp); assert_eq!(downloads.version_downloads.len(), 0); req.with_path("/api/v1/crates/FOO_DOWNLOAD/downloads"); - req.with_query(&("before_date=".to_string() + &strftime("%Y-%m-%d", &yesterday).unwrap())); + req.with_query( + &("before_date=".to_string() + &strftime("%Y-%m-%d", &yesterday).unwrap()), + ); let mut resp = ok_resp!(middle.call(&mut req)); let downloads = ::json::(&mut resp); // crate/downloads always returns the last 90 days and ignores date params @@ -973,12 +977,16 @@ fn download() { let tomorrow = now_utc() + Duration::days(1); req.with_path("/api/v1/crates/FOO_DOWNLOAD/1.0.0/downloads"); - req.with_query(&("before_date=".to_string() + &strftime("%Y-%m-%d", &tomorrow).unwrap())); + req.with_query( + &("before_date=".to_string() + &strftime("%Y-%m-%d", &tomorrow).unwrap()), + ); let mut resp = ok_resp!(middle.call(&mut req)); let downloads = ::json::(&mut resp); assert_eq!(downloads.version_downloads.len(), 1); req.with_path("/api/v1/crates/FOO_DOWNLOAD/downloads"); - req.with_query(&("before_date=".to_string() + &strftime("%Y-%m-%d", &tomorrow).unwrap())); + req.with_query( + &("before_date=".to_string() + &strftime("%Y-%m-%d", &tomorrow).unwrap()), + ); let mut resp = ok_resp!(middle.call(&mut req)); let downloads = ::json::(&mut resp); assert_eq!(downloads.version_downloads.len(), 1); @@ -1144,7 +1152,9 @@ fn owners() { assert_eq!(r.users.len(), 1); let body = r#"{"users":["foobar"]}"#; - let mut response = ok_resp!(middle.call(req.with_method(Method::Put).with_body(body.as_bytes()))); + let mut response = ok_resp!(middle.call(req.with_method(Method::Put).with_body( + body.as_bytes(), + ))); assert!(::json::(&mut response).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get))); @@ -1152,7 +1162,9 @@ fn owners() { assert_eq!(r.users.len(), 2); let body = r#"{"users":["foobar"]}"#; - let mut response = ok_resp!(middle.call(req.with_method(Method::Delete).with_body(body.as_bytes()))); + let mut response = ok_resp!(middle.call(req.with_method(Method::Delete).with_body( + body.as_bytes(), + ))); assert!(::json::(&mut response).ok); let mut response = ok_resp!(middle.call(req.with_method(Method::Get))); @@ -1160,11 +1172,15 @@ fn owners() { assert_eq!(r.users.len(), 1); let body = r#"{"users":["foo"]}"#; - let mut response = ok_resp!(middle.call(req.with_method(Method::Delete).with_body(body.as_bytes()))); + let mut response = ok_resp!(middle.call(req.with_method(Method::Delete).with_body( + body.as_bytes(), + ))); ::json::<::Bad>(&mut response); let body = r#"{"users":["foobar"]}"#; - let mut response = ok_resp!(middle.call(req.with_method(Method::Put).with_body(body.as_bytes()))); + let mut response = ok_resp!(middle.call(req.with_method(Method::Put).with_body( + body.as_bytes(), + ))); assert!(::json::(&mut response).ok); } @@ -1194,21 +1210,15 @@ fn yank() { assert!(contents.contains("\"yanked\":false")); // make sure it's not yanked - let mut r = ok_resp!( - middle.call( - req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk/1.0.0") - ) - ); + let mut r = ok_resp!(middle.call(req.with_method(Method::Get).with_path( + "/api/v1/crates/fyk/1.0.0", + ))); assert!(!::json::(&mut r).version.yanked); // yank it - let mut r = ok_resp!( - middle.call( - req.with_method(Method::Delete) - .with_path("/api/v1/crates/fyk/1.0.0/yank") - ) - ); + let mut r = ok_resp!(middle.call(req.with_method(Method::Delete).with_path( + "/api/v1/crates/fyk/1.0.0/yank", + ))); assert!(::json::(&mut r).ok); let mut contents = String::new(); File::open(&path) @@ -1216,21 +1226,15 @@ fn yank() { .read_to_string(&mut contents) .unwrap(); assert!(contents.contains("\"yanked\":true")); - let mut r = ok_resp!( - middle.call( - req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk/1.0.0") - ) - ); + let mut r = ok_resp!(middle.call(req.with_method(Method::Get).with_path( + "/api/v1/crates/fyk/1.0.0", + ))); assert!(::json::(&mut r).version.yanked); // un-yank it - let mut r = ok_resp!( - middle.call( - req.with_method(Method::Put) - .with_path("/api/v1/crates/fyk/1.0.0/unyank") - ) - ); + let mut r = ok_resp!(middle.call(req.with_method(Method::Put).with_path( + "/api/v1/crates/fyk/1.0.0/unyank", + ))); assert!(::json::(&mut r).ok); let mut contents = String::new(); File::open(&path) @@ -1238,12 +1242,9 @@ fn yank() { .read_to_string(&mut contents) .unwrap(); assert!(contents.contains("\"yanked\":false")); - let mut r = ok_resp!( - middle.call( - req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk/1.0.0") - ) - ); + let mut r = ok_resp!(middle.call(req.with_method(Method::Get).with_path( + "/api/v1/crates/fyk/1.0.0", + ))); assert!(!::json::(&mut r).version.yanked); } @@ -1252,8 +1253,9 @@ fn yank_not_owner() { let (_b, app, middle) = ::app(); let mut req = ::request_with_user_and_mock_crate(&app, ::new_user("bar"), "foo_not"); ::sign_in(&mut req, &app); - req.with_method(Method::Delete) - .with_path("/api/v1/crates/foo_not/1.0.0/yank"); + req.with_method(Method::Delete).with_path( + "/api/v1/crates/foo_not/1.0.0/yank", + ); let mut response = ok_resp!(middle.call(&mut req)); ::json::<::Bad>(&mut response); } @@ -1281,111 +1283,75 @@ fn yank_max_version() { middle.call( req.with_path("/api/v1/crates/new") .with_method(Method::Put) - .with_body(&body) + .with_body(&body), ) ); let json: GoodCrate = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); // yank version 1.0.0 - let mut r = ok_resp!( - middle.call( - req.with_method(Method::Delete) - .with_path("/api/v1/crates/fyk_max/1.0.0/yank") - ) - ); + let mut r = ok_resp!(middle.call(req.with_method(Method::Delete).with_path( + "/api/v1/crates/fyk_max/1.0.0/yank", + ))); assert!(::json::(&mut r).ok); - let mut response = ok_resp!( - middle.call( - req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max") - ) - ); + let mut response = ok_resp!(middle.call(req.with_method(Method::Get).with_path( + "/api/v1/crates/fyk_max", + ))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); // unyank version 1.0.0 - let mut r = ok_resp!( - middle.call( - req.with_method(Method::Put) - .with_path("/api/v1/crates/fyk_max/1.0.0/unyank") - ) - ); + let mut r = ok_resp!(middle.call(req.with_method(Method::Put).with_path( + "/api/v1/crates/fyk_max/1.0.0/unyank", + ))); assert!(::json::(&mut r).ok); - let mut response = ok_resp!( - middle.call( - req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max") - ) - ); + let mut response = ok_resp!(middle.call(req.with_method(Method::Get).with_path( + "/api/v1/crates/fyk_max", + ))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); // yank version 2.0.0 - let mut r = ok_resp!( - middle.call( - req.with_method(Method::Delete) - .with_path("/api/v1/crates/fyk_max/2.0.0/yank") - ) - ); + let mut r = ok_resp!(middle.call(req.with_method(Method::Delete).with_path( + "/api/v1/crates/fyk_max/2.0.0/yank", + ))); assert!(::json::(&mut r).ok); - let mut response = ok_resp!( - middle.call( - req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max") - ) - ); + let mut response = ok_resp!(middle.call(req.with_method(Method::Get).with_path( + "/api/v1/crates/fyk_max", + ))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "1.0.0"); // yank version 1.0.0 - let mut r = ok_resp!( - middle.call( - req.with_method(Method::Delete) - .with_path("/api/v1/crates/fyk_max/1.0.0/yank") - ) - ); + let mut r = ok_resp!(middle.call(req.with_method(Method::Delete).with_path( + "/api/v1/crates/fyk_max/1.0.0/yank", + ))); assert!(::json::(&mut r).ok); - let mut response = ok_resp!( - middle.call( - req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max") - ) - ); + let mut response = ok_resp!(middle.call(req.with_method(Method::Get).with_path( + "/api/v1/crates/fyk_max", + ))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "0.0.0"); // unyank version 2.0.0 - let mut r = ok_resp!( - middle.call( - req.with_method(Method::Put) - .with_path("/api/v1/crates/fyk_max/2.0.0/unyank") - ) - ); + let mut r = ok_resp!(middle.call(req.with_method(Method::Put).with_path( + "/api/v1/crates/fyk_max/2.0.0/unyank", + ))); assert!(::json::(&mut r).ok); - let mut response = ok_resp!( - middle.call( - req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max") - ) - ); + let mut response = ok_resp!(middle.call(req.with_method(Method::Get).with_path( + "/api/v1/crates/fyk_max", + ))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); // unyank version 1.0.0 - let mut r = ok_resp!( - middle.call( - req.with_method(Method::Put) - .with_path("/api/v1/crates/fyk_max/1.0.0/unyank") - ) - ); + let mut r = ok_resp!(middle.call(req.with_method(Method::Put).with_path( + "/api/v1/crates/fyk_max/1.0.0/unyank", + ))); assert!(::json::(&mut r).ok); - let mut response = ok_resp!( - middle.call( - req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max") - ) - ); + let mut response = ok_resp!(middle.call(req.with_method(Method::Get).with_path( + "/api/v1/crates/fyk_max", + ))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); } @@ -1408,19 +1374,13 @@ fn publish_after_yank_max_version() { assert_eq!(json.krate.max_version, "1.0.0"); // yank version 1.0.0 - let mut r = ok_resp!( - middle.call( - req.with_method(Method::Delete) - .with_path("/api/v1/crates/fyk_max/1.0.0/yank") - ) - ); + let mut r = ok_resp!(middle.call(req.with_method(Method::Delete).with_path( + "/api/v1/crates/fyk_max/1.0.0/yank", + ))); assert!(::json::(&mut r).ok); - let mut response = ok_resp!( - middle.call( - req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max") - ) - ); + let mut response = ok_resp!(middle.call(req.with_method(Method::Get).with_path( + "/api/v1/crates/fyk_max", + ))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "0.0.0"); @@ -1430,26 +1390,20 @@ fn publish_after_yank_max_version() { middle.call( req.with_path("/api/v1/crates/new") .with_method(Method::Put) - .with_body(&body) + .with_body(&body), ) ); let json: GoodCrate = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); // unyank version 1.0.0 - let mut r = ok_resp!( - middle.call( - req.with_method(Method::Put) - .with_path("/api/v1/crates/fyk_max/1.0.0/unyank") - ) - ); + let mut r = ok_resp!(middle.call(req.with_method(Method::Put).with_path( + "/api/v1/crates/fyk_max/1.0.0/unyank", + ))); assert!(::json::(&mut r).ok); - let mut response = ok_resp!( - middle.call( - req.with_method(Method::Get) - .with_path("/api/v1/crates/fyk_max") - ) - ); + let mut response = ok_resp!(middle.call(req.with_method(Method::Get).with_path( + "/api/v1/crates/fyk_max", + ))); let json: CrateResponse = ::json(&mut response); assert_eq!(json.krate.max_version, "2.0.0"); } @@ -1545,12 +1499,9 @@ fn good_badges() { assert_eq!(json.krate.name, "foobadger"); assert_eq!(json.krate.max_version, "1.0.0"); - let mut response = ok_resp!( - middle.call( - req.with_method(Method::Get) - .with_path("/api/v1/crates/foobadger") - ) - ); + let mut response = ok_resp!(middle.call(req.with_method(Method::Get).with_path( + "/api/v1/crates/foobadger", + ))); let json: CrateResponse = ::json(&mut response); @@ -1588,23 +1539,16 @@ fn ignored_badges() { assert_eq!(json.krate.name, "foo_ignored_badge"); assert_eq!(json.krate.max_version, "1.0.0"); assert_eq!(json.warnings.invalid_badges.len(), 2); - assert!( - json.warnings - .invalid_badges - .contains(&"travis-ci".to_string()) - ); - assert!( - json.warnings - .invalid_badges - .contains(&"not-a-badge".to_string()) - ); + assert!(json.warnings.invalid_badges.contains( + &"travis-ci".to_string(), + )); + assert!(json.warnings.invalid_badges.contains( + &"not-a-badge".to_string(), + )); - let mut response = ok_resp!( - middle.call( - req.with_method(Method::Get) - .with_path("/api/v1/crates/foo_ignored_badge") - ) - ); + let mut response = ok_resp!(middle.call(req.with_method(Method::Get).with_path( + "/api/v1/crates/foo_ignored_badge", + ))); let json: CrateResponse = ::json(&mut response); @@ -1747,8 +1691,7 @@ fn author_license_and_description_required() { req.with_body(&::new_crate_to_body(&new_crate, &[])); let json = bad_resp!(middle.call(&mut req)); assert!( - json.errors[0].detail.contains("author") && json.errors[0].detail.contains("description") && - json.errors[0].detail.contains("license"), + json.errors[0].detail.contains("author") && json.errors[0].detail.contains("description") && json.errors[0].detail.contains("license"), "{:?}", json.errors ); @@ -1758,8 +1701,7 @@ fn author_license_and_description_required() { req.with_body(&::new_crate_to_body(&new_crate, &[])); let json = bad_resp!(middle.call(&mut req)); assert!( - json.errors[0].detail.contains("author") && json.errors[0].detail.contains("description") && - !json.errors[0].detail.contains("license"), + json.errors[0].detail.contains("author") && json.errors[0].detail.contains("description") && !json.errors[0].detail.contains("license"), "{:?}", json.errors ); @@ -1770,8 +1712,7 @@ fn author_license_and_description_required() { req.with_body(&::new_crate_to_body(&new_crate, &[])); let json = bad_resp!(middle.call(&mut req)); assert!( - !json.errors[0].detail.contains("author") && json.errors[0].detail.contains("description") && - !json.errors[0].detail.contains("license"), + !json.errors[0].detail.contains("author") && json.errors[0].detail.contains("description") && !json.errors[0].detail.contains("license"), "{:?}", json.errors ); diff --git a/src/tests/record.rs b/src/tests/record.rs index 8e68f8c52c1..de0d26a869f 100644 --- a/src/tests/record.rs +++ b/src/tests/record.rs @@ -86,50 +86,48 @@ pub fn proxy() -> (String, Bomb) { let (quittx, quitrx) = channel(); - thread::spawn( - move || { - let mut file = None; - for socket in a.incoming() { - if quitrx.try_recv().is_ok() { - break; - } - let socket = t!(socket); - - if file.is_none() { - let io = t!( - if record { - File::create(&data) - } else { - File::open(&data) - } - ); - file = Some(BufStream::new(io)); - } + thread::spawn(move || { + let mut file = None; + for socket in a.incoming() { + if quitrx.try_recv().is_ok() { + break; + } + let socket = t!(socket); - if record { - record_http(socket, file.as_mut().unwrap()); + if file.is_none() { + let io = t!(if record { + File::create(&data) } else { - replay_http(socket, file.as_mut().unwrap(), &mut sink2); - } + File::open(&data) + }); + file = Some(BufStream::new(io)); } - if !record { - if let Some(mut f) = file { - let mut s = String::new(); - t!(f.read_line(&mut s)); - assert_eq!(s, ""); - } + + if record { + record_http(socket, file.as_mut().unwrap()); + } else { + replay_http(socket, file.as_mut().unwrap(), &mut sink2); } - tx.send(()).unwrap(); } - ); - - (ret, - Bomb { - accept: a2, - rx: rx, - iorx: Sink(sink), - quit: quittx, - }) + if !record { + if let Some(mut f) = file { + let mut s = String::new(); + t!(f.read_line(&mut s)); + assert_eq!(s, ""); + } + } + tx.send(()).unwrap(); + }); + + ( + ret, + Bomb { + accept: a2, + rx: rx, + iorx: Sink(sink), + quit: quittx, + }, + ) } fn record_http(mut socket: TcpStream, data: &mut BufStream) { @@ -141,16 +139,14 @@ fn record_http(mut socket: TcpStream, data: &mut BufStream) { respond(handle, headers, body, &mut response); t!(socket.write_all(&response)); - t!( - write!( - data, - "===REQUEST {}\n{}\n===RESPONSE {}\n{}\n", - request.len(), - str::from_utf8(&request).unwrap(), - response.len(), - str::from_utf8(&response).unwrap() - ) - ); + t!(write!( + data, + "===REQUEST {}\n{}\n===RESPONSE {}\n{}\n", + request.len(), + str::from_utf8(&request).unwrap(), + response.len(), + str::from_utf8(&response).unwrap() + )); fn send(rdr: R) -> (Easy, Vec>, Vec) { let mut socket = BufReader::new(rdr); @@ -187,23 +183,17 @@ fn record_http(mut socket: TcpStream, data: &mut BufStream) { let mut response = Vec::new(); { let mut transfer = handle.transfer(); - t!( - transfer.header_function( - |header| { - headers.push(header.to_owned()); - true - } - ) - ); - t!( - transfer.write_function( - |data| { - response.extend(data); - Ok(data.len()) - } - ) - ); - t!(transfer.read_function(|buf| socket.read(buf).map_err(|_| ReadError::Abort))); + t!(transfer.header_function(|header| { + headers.push(header.to_owned()); + true + })); + t!(transfer.write_function(|data| { + response.extend(data); + Ok(data.len()) + })); + t!(transfer.read_function( + |buf| socket.read(buf).map_err(|_| ReadError::Abort), + )); t!(transfer.perform()); } @@ -212,7 +202,9 @@ fn record_http(mut socket: TcpStream, data: &mut BufStream) { } fn respond(mut handle: Easy, headers: Vec>, body: Vec, mut socket: W) { - t!(socket.write_all(format!("HTTP/1.1 {}\r\n", t!(handle.response_code())).as_bytes())); + t!(socket.write_all( + format!("HTTP/1.1 {}\r\n", t!(handle.response_code())).as_bytes(), + )); for header in headers { if header.starts_with(b"Transfer-Encoding: ") { continue; @@ -334,15 +326,12 @@ impl GhUser { self.login, password ); - let body = json::encode( - &Authorization { - scopes: vec!["read:org".to_string()], - note: "crates.io test".to_string(), - client_id: ::env("GH_CLIENT_ID"), - client_secret: ::env("GH_CLIENT_SECRET"), - } - ) - .unwrap(); + let body = json::encode(&Authorization { + scopes: vec!["read:org".to_string()], + note: "crates.io test".to_string(), + client_id: ::env("GH_CLIENT_ID"), + client_secret: ::env("GH_CLIENT_SECRET"), + }).unwrap(); t!(handle.url(&url)); t!(handle.post(true)); @@ -355,15 +344,13 @@ impl GhUser { let mut response = Vec::new(); { let mut transfer = handle.transfer(); - t!(transfer.read_function(|buf| body.read(buf).map_err(|_| ReadError::Abort))); - t!( - transfer.write_function( - |data| { - response.extend(data); - Ok(data.len()) - } - ) - ); + t!(transfer.read_function( + |buf| body.read(buf).map_err(|_| ReadError::Abort), + )); + t!(transfer.write_function(|data| { + response.extend(data); + Ok(data.len()) + })); t!(transfer.perform()) } diff --git a/src/tests/team.rs b/src/tests/team.rs index 29b35b243db..b9658a563c1 100644 --- a/src/tests/team.rs +++ b/src/tests/team.rs @@ -44,7 +44,7 @@ fn not_github() { middle.call( req.with_path("/api/v1/crates/foo_not_github/owners") .with_method(Method::Put) - .with_body(body.as_bytes()) + .with_body(body.as_bytes()), ) ); assert!( @@ -64,13 +64,13 @@ fn weird_name() { middle.call( req.with_path("/api/v1/crates/foo_weird_name/owners") .with_method(Method::Put) - .with_body(body.as_bytes()) + .with_body(body.as_bytes()), ) ); assert!( - json.errors[0] - .detail - .contains("organization cannot contain"), + json.errors[0].detail.contains( + "organization cannot contain", + ), "{:?}", json.errors ); @@ -87,7 +87,7 @@ fn one_colon() { middle.call( req.with_path("/api/v1/crates/foo_one_colon/owners") .with_method(Method::Put) - .with_body(body.as_bytes()) + .with_body(body.as_bytes()), ) ); assert!( @@ -107,13 +107,13 @@ fn nonexistent_team() { middle.call( req.with_path("/api/v1/crates/foo_nonexistent/owners") .with_method(Method::Put) - .with_body(body.as_bytes()) + .with_body(body.as_bytes()), ) ); assert!( - json.errors[0] - .detail - .contains("could not find the github team"), + json.errors[0].detail.contains( + "could not find the github team", + ), "{:?}", json.errors ); @@ -130,7 +130,7 @@ fn add_team_as_member() { middle.call( req.with_path("/api/v1/crates/foo_team_member/owners") .with_method(Method::Put) - .with_body(body.as_bytes()) + .with_body(body.as_bytes()), ) ); } @@ -146,7 +146,7 @@ fn add_team_as_non_member() { middle.call( req.with_path("/api/v1/crates/foo_team_non_member/owners") .with_method(Method::Put) - .with_body(body.as_bytes()) + .with_body(body.as_bytes()), ) ); assert!( @@ -166,7 +166,7 @@ fn remove_team_as_named_owner() { middle.call( req.with_path("/api/v1/crates/foo_remove_team/owners") .with_method(Method::Put) - .with_body(body.as_bytes()) + .with_body(body.as_bytes()), ) ); @@ -175,7 +175,7 @@ fn remove_team_as_named_owner() { middle.call( req.with_path("/api/v1/crates/foo_remove_team/owners") .with_method(Method::Delete) - .with_body(body.as_bytes()) + .with_body(body.as_bytes()), ) ); @@ -189,7 +189,7 @@ fn remove_team_as_named_owner() { middle.call( req.with_path("/api/v1/crates/new") .with_body(&body) - .with_method(Method::Put) + .with_method(Method::Put), ) ); assert!( @@ -209,7 +209,7 @@ fn remove_team_as_team_owner() { middle.call( req.with_path("/api/v1/crates/foo_remove_team_owner/owners") .with_method(Method::Put) - .with_body(body.as_bytes()) + .with_body(body.as_bytes()), ) ); @@ -223,7 +223,7 @@ fn remove_team_as_team_owner() { middle.call( req.with_path("/api/v1/crates/foo_remove_team_owner/owners") .with_method(Method::Delete) - .with_body(body.as_bytes()) + .with_body(body.as_bytes()), ) ); @@ -238,7 +238,7 @@ fn remove_team_as_team_owner() { middle.call( req.with_path("/api/v1/crates/new") .with_body(&body) - .with_method(Method::Put) + .with_method(Method::Put), ) ); } @@ -255,7 +255,7 @@ fn publish_not_owned() { middle.call( req.with_path("/api/v1/crates/foo_not_owned/owners") .with_method(Method::Put) - .with_body(body.as_bytes()) + .with_body(body.as_bytes()), ) ); @@ -269,7 +269,7 @@ fn publish_not_owned() { middle.call( req.with_path("/api/v1/crates/new") .with_body(&body) - .with_method(Method::Put) + .with_method(Method::Put), ) ); assert!( @@ -290,7 +290,7 @@ fn publish_owned() { middle.call( req.with_path("/api/v1/crates/foo_team_owned/owners") .with_method(Method::Put) - .with_body(body.as_bytes()) + .with_body(body.as_bytes()), ) ); @@ -304,7 +304,7 @@ fn publish_owned() { middle.call( req.with_path("/api/v1/crates/new") .with_body(&body) - .with_method(Method::Put) + .with_method(Method::Put), ) ); } @@ -320,7 +320,7 @@ fn add_owners_as_team_owner() { middle.call( req.with_path("/api/v1/crates/foo_add_owner/owners") .with_method(Method::Put) - .with_body(body.as_bytes()) + .with_body(body.as_bytes()), ) ); @@ -334,7 +334,7 @@ fn add_owners_as_team_owner() { middle.call( req.with_path("/api/v1/crates/foo_add_owner/owners") .with_method(Method::Put) - .with_body(body.as_bytes()) + .with_body(body.as_bytes()), ) ); assert!( diff --git a/src/tests/user.rs b/src/tests/user.rs index 8c25b8581c2..0e99b3d1246 100644 --- a/src/tests/user.rs +++ b/src/tests/user.rs @@ -163,7 +163,9 @@ fn following() { .expect_build(&conn); } - let mut response = ok_resp!(middle.call(req.with_path("/me/updates").with_method(Method::Get))); + let mut response = ok_resp!(middle.call( + req.with_path("/me/updates").with_method(Method::Get), + )); let r = ::json::(&mut response); assert_eq!(r.versions.len(), 0); assert_eq!(r.meta.more, false); @@ -171,17 +173,19 @@ fn following() { ok_resp!( middle.call( req.with_path("/api/v1/crates/foo_fighters/follow") - .with_method(Method::Put) + .with_method(Method::Put), ) ); ok_resp!( middle.call( req.with_path("/api/v1/crates/bar_fighters/follow") - .with_method(Method::Put) + .with_method(Method::Put), ) ); - let mut response = ok_resp!(middle.call(req.with_path("/me/updates").with_method(Method::Get))); + let mut response = ok_resp!(middle.call( + req.with_path("/me/updates").with_method(Method::Get), + )); let r = ::json::(&mut response); assert_eq!(r.versions.len(), 2); assert_eq!(r.meta.more, false); @@ -190,7 +194,7 @@ fn following() { middle.call( req.with_path("/me/updates") .with_method(Method::Get) - .with_query("per_page=1") + .with_query("per_page=1"), ) ); let r = ::json::(&mut response); @@ -200,14 +204,14 @@ fn following() { ok_resp!( middle.call( req.with_path("/api/v1/crates/bar_fighters/follow") - .with_method(Method::Delete) + .with_method(Method::Delete), ) ); let mut response = ok_resp!( middle.call( req.with_path("/me/updates") .with_method(Method::Get) - .with_query("page=2&per_page=1") + .with_query("page=2&per_page=1"), ) ); let r = ::json::(&mut response); diff --git a/src/upload.rs b/src/upload.rs index 730e0caed78..b450b1d600c 100644 --- a/src/upload.rs +++ b/src/upload.rs @@ -52,14 +52,14 @@ impl Decodable for CrateName { fn decode(d: &mut D) -> Result { let s = d.read_str()?; if !Crate::valid_name(&s) { - return Err( - d.error( - &format!("invalid crate name specified: {}. \ + return Err(d.error(&format!( + "invalid crate name specified: {}. \ Valid crate names must start with a letter; contain only \ letters, numbers, hyphens, or underscores; and have {} or \ - fewer characters.", s, MAX_NAME_LENGTH) - ) - ); + fewer characters.", + s, + MAX_NAME_LENGTH + ))); } Ok(CrateName(s)) } @@ -137,12 +137,10 @@ impl Decodable for KeywordList { } for val in &inner { if val.len() > 20 { - return Err( - d.error( - "keywords must contain less than 20 \ - characters" - ) - ); + return Err(d.error( + "keywords must contain less than 20 \ + characters", + )); } } Ok(KeywordList(inner)) @@ -167,12 +165,11 @@ impl Decodable for DependencyKind { "build" => Ok(DependencyKind::Build), "normal" => Ok(DependencyKind::Normal), s => { - Err( - d.error( - &format!("invalid dependency kind `{}`, must be \ - one of dev, build, or normal", s) - ) - ) + Err(d.error(&format!( + "invalid dependency kind `{}`, must be \ + one of dev, build, or normal", + s + ))) } } } diff --git a/src/uploaders.rs b/src/uploaders.rs index 76f481aaa61..d9cfb107a84 100644 --- a/src/uploaders.rs +++ b/src/uploaders.rs @@ -38,17 +38,17 @@ impl Uploader { pub fn crate_location(&self, crate_name: &str, version: &str) -> Option { match *self { Uploader::S3 { ref bucket, .. } => { - Some( - format!("https://{}/{}", - bucket.host(), - Uploader::crate_path(crate_name, version)) - ) + Some(format!( + "https://{}/{}", + bucket.host(), + Uploader::crate_path(crate_name, version) + )) } Uploader::Local => { - Some( - format!("/local_uploads/{}", - Uploader::crate_path(crate_name, version)) - ) + Some(format!( + "/local_uploads/{}", + Uploader::crate_path(crate_name, version) + )) } Uploader::NoOp => None, } @@ -78,36 +78,32 @@ impl Uploader { length as u64, ); s3req - .write_function( - |data| { - response.extend(data); - Ok(data.len()) - } - ) + .write_function(|data| { + response.extend(data); + Ok(data.len()) + }) .unwrap(); - s3req - .perform() - .chain_error(|| internal(&format_args!("failed to upload to S3: `{}`", path)))?; + s3req.perform().chain_error(|| { + internal(&format_args!("failed to upload to S3: `{}`", path)) + })?; } (response, body.finalize()) }; if handle.response_code().unwrap() != 200 { let response = String::from_utf8_lossy(&response); - return Err( - internal( - &format_args!("failed to get a 200 response from S3: {}", - response) - ) - ); + return Err(internal(&format_args!( + "failed to get a 200 response from S3: {}", + response + ))); } - Ok( - (cksum, - Bomb { - app: req.app().clone(), - path: Some(path), - }) - ) + Ok(( + cksum, + Bomb { + app: req.app().clone(), + path: Some(path), + }, + )) } Uploader::Local => { let path = Uploader::crate_path(&krate.name, &vers.to_string()); @@ -131,22 +127,22 @@ impl Uploader { body.finalize() }; - Ok( - (cksum, - Bomb { - app: req.app().clone(), - path: crate_filename.to_str().map(String::from), - }) - ) + Ok(( + cksum, + Bomb { + app: req.app().clone(), + path: crate_filename.to_str().map(String::from), + }, + )) } Uploader::NoOp => { - Ok( - (vec![], - Bomb { - app: req.app().clone(), - path: None, - }) - ) + Ok(( + vec![], + Bomb { + app: req.app().clone(), + path: None, + }, + )) } } } diff --git a/src/user/middleware.rs b/src/user/middleware.rs index 2b5b256b606..5c84c83aaf9 100644 --- a/src/user/middleware.rs +++ b/src/user/middleware.rs @@ -61,8 +61,8 @@ pub trait RequestUser { impl<'a> RequestUser for Request + 'a { fn user(&self) -> CargoResult<&User> { - self.extensions() - .find::() - .chain_error(|| Unauthorized) + self.extensions().find::().chain_error( + || Unauthorized, + ) } } diff --git a/src/user/mod.rs b/src/user/mod.rs index d44c42f3edf..6abe86a8724 100644 --- a/src/user/mod.rs +++ b/src/user/mod.rs @@ -35,7 +35,7 @@ pub struct User { } #[derive(Insertable, AsChangeset)] -#[table_name="users"] +#[table_name = "users"] pub struct NewUser<'a> { pub gh_id: i32, pub gh_login: &'a str, @@ -46,14 +46,7 @@ pub struct NewUser<'a> { } impl<'a> NewUser<'a> { - pub fn new( - gh_id: i32, - gh_login: &'a str, - email: Option<&'a str>, - name: Option<&'a str>, - gh_avatar: Option<&'a str>, - gh_access_token: &'a str, - ) -> Self { + pub fn new(gh_id: i32, gh_login: &'a str, email: Option<&'a str>, name: Option<&'a str>, gh_avatar: Option<&'a str>, gh_access_token: &'a str) -> Self { NewUser { gh_id: gh_id, gh_login: gh_login, @@ -94,9 +87,9 @@ impl User { /// Queries the database for a user with a certain `gh_login` value. pub fn find_by_login(conn: &GenericConnection, login: &str) -> CargoResult { let stmt = conn.prepare( - "SELECT * FROM users - WHERE gh_login = $1" - )?; + "SELECT * FROM users + WHERE gh_login = $1", + )?; let rows = stmt.query(&[&login])?; let row = rows.iter().next().chain_error(|| NotFound)?; Ok(Model::from_row(&row)) @@ -105,9 +98,9 @@ impl User { /// Queries the database for a user with a certain `api_token` value. pub fn find_by_api_token(conn: &GenericConnection, token: &str) -> CargoResult { let stmt = conn.prepare( - "SELECT * FROM users \ - WHERE api_token = $1 LIMIT 1" - )?; + "SELECT * FROM users \ + WHERE api_token = $1 LIMIT 1", + )?; let rows = stmt.query(&[&token])?; rows.iter() .next() @@ -130,34 +123,34 @@ impl User { // more errors than it needs to. let stmt = conn.prepare( - "UPDATE users + "UPDATE users SET gh_access_token = $1, email = $2, name = $3, gh_avatar = $4, gh_login = $5 WHERE gh_id = $6 - RETURNING *" - )?; - let rows = stmt.query(&[&access_token, &email, &name, &avatar, &login, &id])?; + RETURNING *", + )?; + let rows = stmt.query( + &[&access_token, &email, &name, &avatar, &login, &id], + )?; if let Some(ref row) = rows.iter().next() { return Ok(Model::from_row(row)); } let stmt = conn.prepare( - "INSERT INTO users + "INSERT INTO users (email, gh_access_token, gh_login, name, gh_avatar, gh_id) VALUES ($1, $2, $3, $4, $5, $6) - RETURNING *" - )?; - let rows = stmt.query(&[&email, &access_token, &login, &name, &avatar, &id])?; - Ok( - Model::from_row( - &rows.iter() - .next() - .chain_error(|| internal("no user with email we just found"))? - ) - ) + RETURNING *", + )?; + let rows = stmt.query( + &[&email, &access_token, &login, &name, &avatar, &id], + )?; + Ok(Model::from_row(&rows.iter().next().chain_error(|| { + internal("no user with email we just found") + })?)) } /// Converts this `User` model into an `EncodableUser` for JSON serialization. @@ -219,8 +212,10 @@ impl Model for User { pub fn github_authorize(req: &mut Request) -> CargoResult { // Generate a random 16 char ASCII string let state: String = thread_rng().gen_ascii_chars().take(16).collect(); - req.session() - .insert("github_oauth_state".to_string(), state.clone()); + req.session().insert( + "github_oauth_state".to_string(), + state.clone(), + ); let url = req.app().github.authorize_url(state.clone()); @@ -229,14 +224,10 @@ pub fn github_authorize(req: &mut Request) -> CargoResult { url: String, state: String, } - Ok( - req.json( - &R { - url: url.to_string(), - state: state, - } - ) - ) + Ok(req.json(&R { + url: url.to_string(), + state: state, + })) } /// Handles the `GET /authorize` route. @@ -293,10 +284,9 @@ pub fn github_access_token(req: &mut Request) -> CargoResult { } // Fetch the access token from github using the code we just got - let token = req.app() - .github - .exchange(code.clone()) - .map_err(|s| human(&s))?; + let token = req.app().github.exchange(code.clone()).map_err( + |s| human(&s), + )?; let (handle, resp) = http::github(req.app(), "/user", &token)?; let ghuser: GithubUser = http::parse_github_response(handle, &resp)?; @@ -310,8 +300,10 @@ pub fn github_access_token(req: &mut Request) -> CargoResult { ghuser.avatar_url.as_ref().map(|s| &s[..]), &token.access_token, )?; - req.session() - .insert("user_id".to_string(), user.id.to_string()); + req.session().insert( + "user_id".to_string(), + user.id.to_string(), + ); req.mut_extensions().insert(user); me(req) } @@ -328,14 +320,13 @@ pub fn reset_token(req: &mut Request) -> CargoResult { let conn = req.tx()?; let rows = conn.query( - "UPDATE users SET api_token = DEFAULT \ + "UPDATE users SET api_token = DEFAULT \ WHERE id = $1 RETURNING api_token", - &[&user.id], - )?; - let token = rows.iter() - .next() - .map(|r| r.get("api_token")) - .chain_error(|| NotFound)?; + &[&user.id], + )?; + let token = rows.iter().next().map(|r| r.get("api_token")).chain_error( + || NotFound, + )?; #[derive(RustcEncodable)] struct R { @@ -354,14 +345,10 @@ pub fn me(req: &mut Request) -> CargoResult { api_token: String, } let token = user.api_token.clone(); - Ok( - req.json( - &R { - user: user.clone().encodable(), - api_token: token, - } - ) - ) + Ok(req.json(&R { + user: user.clone().encodable(), + api_token: token, + })) } /// Handles the `GET /users/:user_id` route. @@ -396,7 +383,11 @@ pub fn updates(req: &mut Request) -> CargoResult { .order(versions::created_at.desc()) .limit(limit) .offset(offset) - .select((versions::all_columns, crates::name, sql::("COUNT(*) OVER ()"))) + .select(( + versions::all_columns, + crates::name, + sql::("COUNT(*) OVER ()"), + )) .load::<(Version, String, i64)>(&*conn)?; let more = data.get(0) @@ -416,14 +407,10 @@ pub fn updates(req: &mut Request) -> CargoResult { struct Meta { more: bool, } - Ok( - req.json( - &R { - versions: versions, - meta: Meta { more: more }, - } - ) - ) + Ok(req.json(&R { + versions: versions, + meta: Meta { more: more }, + })) } #[cfg(test)] diff --git a/src/util/errors.rs b/src/util/errors.rs index fcf2125f49d..f89d9d6d43f 100644 --- a/src/util/errors.rs +++ b/src/util/errors.rs @@ -27,7 +27,9 @@ pub trait CargoError: Send + fmt::Display + 'static { fn response(&self) -> Option { if self.human() { - Some(json_response(&Bad { errors: vec![StringError { detail: self.description().to_string() }] })) + Some(json_response(&Bad { + errors: vec![StringError { detail: self.description().to_string() }], + })) } else { self.cause().and_then(|cause| cause.response()) } @@ -109,16 +111,12 @@ impl ChainError for Result { E2: CargoError, C: FnOnce() -> E2, { - self.map_err( - move |err| { - Box::new( - ChainedError { - error: callback(), - cause: Box::new(err), - } - ) as Box - } - ) + self.map_err(move |err| { + Box::new(ChainedError { + error: callback(), + cause: Box::new(err), + }) as Box + }) } } @@ -233,7 +231,9 @@ impl CargoError for NotFound { } fn response(&self) -> Option { - let mut response = json_response(&Bad { errors: vec![StringError { detail: "Not Found".to_string() }] }); + let mut response = json_response(&Bad { + errors: vec![StringError { detail: "Not Found".to_string() }], + }); response.status = (404, "Not Found"); Some(response) } @@ -253,13 +253,11 @@ impl CargoError for Unauthorized { } fn response(&self) -> Option { - let mut response = json_response( - &Bad { - errors: vec![StringError { - detail: "must be logged in to perform that action".to_string(), - }], - } - ); + let mut response = json_response(&Bad { + errors: vec![ + StringError { detail: "must be logged in to perform that action".to_string() }, + ], + }); response.status = (403, "Forbidden"); Some(response) } @@ -272,36 +270,30 @@ impl fmt::Display for Unauthorized { } pub fn internal_error(error: &str, detail: &str) -> Box { - Box::new( - ConcreteCargoError { - description: error.to_string(), - detail: Some(detail.to_string()), - cause: None, - human: false, - } - ) + Box::new(ConcreteCargoError { + description: error.to_string(), + detail: Some(detail.to_string()), + cause: None, + human: false, + }) } pub fn internal(error: &S) -> Box { - Box::new( - ConcreteCargoError { - description: error.to_string(), - detail: None, - cause: None, - human: false, - } - ) + Box::new(ConcreteCargoError { + description: error.to_string(), + detail: None, + cause: None, + human: false, + }) } pub fn human(error: &S) -> Box { - Box::new( - ConcreteCargoError { - description: error.to_string(), - detail: None, - cause: None, - human: true, - } - ) + Box::new(ConcreteCargoError { + description: error.to_string(), + detail: None, + cause: None, + human: true, + }) } pub fn std_error(e: Box) -> Box { diff --git a/src/util/hasher.rs b/src/util/hasher.rs index 468c18c0a1d..52132eb2c2f 100644 --- a/src/util/hasher.rs +++ b/src/util/hasher.rs @@ -17,7 +17,8 @@ impl HashingReader { pub fn finalize(mut self) -> Vec { #[allow(deprecated)] - self.hasher.finish().unwrap() +#[allow(deprecated)] #[allow(deprecated)] + #[allow(deprecated)] self.hasher.finish().unwrap() } } diff --git a/src/util/head.rs b/src/util/head.rs index 115feae3e5b..36202d76513 100644 --- a/src/util/head.rs +++ b/src/util/head.rs @@ -25,18 +25,12 @@ impl Handler for Head { path: None, method: Some(Method::Get), }; - self.handler - .as_ref() - .unwrap() - .call(&mut req) - .map( - |r| { - Response { - body: Box::new(io::empty()), - ..r - } - } - ) + self.handler.as_ref().unwrap().call(&mut req).map(|r| { + Response { + body: Box::new(io::empty()), + ..r + } + }) } else { self.handler.as_ref().unwrap().call(req) } diff --git a/src/util/io_util.rs b/src/util/io_util.rs index 520431bea48..be25ddd14f0 100644 --- a/src/util/io_util.rs +++ b/src/util/io_util.rs @@ -15,7 +15,10 @@ impl LimitErrorReader { impl Read for LimitErrorReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { match self.inner.read(buf) { - Ok(0) if self.inner.limit() == 0 => Err(io::Error::new(io::ErrorKind::Other, "maximum limit reached when reading")), + Ok(0) if self.inner.limit() == 0 => Err(io::Error::new( + io::ErrorKind::Other, + "maximum limit reached when reading", + )), e => e, } } @@ -24,7 +27,9 @@ impl Read for LimitErrorReader { pub fn read_le_u32(r: &mut R) -> io::Result { let mut b = [0; 4]; read_fill(r, &mut b)?; - Ok((b[0] as u32) | ((b[1] as u32) << 8) | ((b[2] as u32) << 16) | ((b[3] as u32) << 24)) + Ok( + (b[0] as u32) | ((b[1] as u32) << 8) | ((b[2] as u32) << 16) | ((b[3] as u32) << 24), + ) } pub fn read_fill(r: &mut R, mut slice: &mut [u8]) -> io::Result<()> { diff --git a/src/util/mod.rs b/src/util/mod.rs index fb197be25b7..02a8d2e4696 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -46,10 +46,10 @@ pub fn json_response(t: &T) -> Response { ); headers.insert("Content-Length".to_string(), vec![json.len().to_string()]); return Response { - status: (200, "OK"), - headers: headers, - body: Box::new(Cursor::new(json.into_bytes())), - }; + status: (200, "OK"), + headers: headers, + body: Box::new(Cursor::new(json.into_bytes())), + }; fn fixup(json: Json) -> Json { match json { @@ -57,13 +57,11 @@ pub fn json_response(t: &T) -> Response { Json::Object( object .into_iter() - .map( - |(k, v)| { - let k = if k == "krate" { "crate".to_string() } else { k }; - (k, fixup(v)) - } - ) - .collect() + .map(|(k, v)| { + let k = if k == "krate" { "crate".to_string() } else { k }; + (k, fixup(v)) + }) + .collect(), ) } Json::Array(list) => Json::Array(list.into_iter().map(fixup).collect()), @@ -112,7 +110,9 @@ impl<'a> RequestUtils for Request + 'a { .and_then(|s| s.parse::().ok()) .unwrap_or(default); if limit > max { - return Err(human(&format_args!("cannot request more than {} items", max))); + return Err(human( + &format_args!("cannot request more than {} items", max), + )); } if page == 0 { return Err(human("page indexing starts from 1, page 0 is invalid")); @@ -147,13 +147,11 @@ impl Handler for R { fn call(&self, req: &mut Request) -> Result> { let path = req.params()["path"].to_string(); let R(ref sub_router) = *self; - sub_router.call( - &mut RequestProxy { - other: req, - path: Some(&path), - method: None, - } - ) + sub_router.call(&mut RequestProxy { + other: req, + path: Some(&path), + method: None, + }) } } diff --git a/src/util/request_proxy.rs b/src/util/request_proxy.rs index 8c1929db133..5409b318b4a 100644 --- a/src/util/request_proxy.rs +++ b/src/util/request_proxy.rs @@ -19,9 +19,9 @@ impl<'a> Request for RequestProxy<'a> { self.other.conduit_version() } fn method(&self) -> conduit::Method { - self.method - .clone() - .unwrap_or_else(|| self.other.method().clone()) + self.method.clone().unwrap_or_else( + || self.other.method().clone(), + ) } fn scheme(&self) -> conduit::Scheme { self.other.scheme() diff --git a/src/version.rs b/src/version.rs index 38d51c205da..8bdb9acbb27 100644 --- a/src/version.rs +++ b/src/version.rs @@ -38,7 +38,7 @@ pub struct Version { } #[derive(Insertable)] -#[table_name="versions"] +#[table_name = "versions"] pub struct NewVersion { crate_id: i32, num: String, @@ -74,9 +74,9 @@ impl Version { pub fn find_by_num(conn: &GenericConnection, crate_id: i32, num: &semver::Version) -> CargoResult> { let num = num.to_string(); let stmt = conn.prepare( - "SELECT * FROM versions \ - WHERE crate_id = $1 AND num = $2" - )?; + "SELECT * FROM versions \ + WHERE crate_id = $1 AND num = $2", + )?; let rows = stmt.query(&[&crate_id, &num])?; Ok(rows.iter().next().map(|r| Model::from_row(&r))) } @@ -91,17 +91,15 @@ impl Version { let num = num.to_string(); let features = json::encode(features).unwrap(); let stmt = conn.prepare( - "INSERT INTO versions \ + "INSERT INTO versions \ (crate_id, num, features) \ VALUES ($1, $2, $3) \ - RETURNING *" - )?; + RETURNING *", + )?; let rows = stmt.query(&[&crate_id, &num, &features])?; - let ret: Version = Model::from_row( - &rows.iter() - .next() - .chain_error(|| internal("no version returned"))? - ); + let ret: Version = Model::from_row(&rows.iter().next().chain_error( + || internal("no version returned"), + )?); for author in authors { ret.add_author(conn, author)?; } @@ -135,10 +133,8 @@ impl Version { features: features, yanked: yanked, links: VersionLinks { - dependencies: format!("/api/v1/crates/{}/{}/dependencies", - crate_name, num), - version_downloads: format!("/api/v1/crates/{}/{}/downloads", - crate_name, num), + dependencies: format!("/api/v1/crates/{}/{}/dependencies", crate_name, num), + version_downloads: format!("/api/v1/crates/{}/{}/downloads", crate_name, num), authors: format!("/api/v1/crates/{}/{}/authors", crate_name, num), }, } @@ -155,32 +151,32 @@ impl Version { pub fn authors(&self, conn: &GenericConnection) -> CargoResult> { let stmt = conn.prepare( - "SELECT * FROM version_authors + "SELECT * FROM version_authors WHERE version_id = $1 - ORDER BY name ASC" - )?; + ORDER BY name ASC", + )?; let rows = stmt.query(&[&self.id])?; Ok( rows.into_iter() .map(|row| Author { name: row.get("name") }) - .collect() + .collect(), ) } pub fn add_author(&self, conn: &GenericConnection, name: &str) -> CargoResult<()> { conn.execute( - "INSERT INTO version_authors (version_id, name) + "INSERT INTO version_authors (version_id, name) VALUES ($1, $2)", - &[&self.id, &name], - )?; + &[&self.id, &name], + )?; Ok(()) } pub fn yank(&self, conn: &GenericConnection, yanked: bool) -> CargoResult<()> { conn.execute( - "UPDATE versions SET yanked = $1 WHERE id = $2", - &[&yanked, &self.id], - )?; + "UPDATE versions SET yanked = $1 WHERE id = $2", + &[&yanked, &self.id], + )?; Ok(()) } @@ -188,33 +184,26 @@ impl Version { where T: IntoIterator, { - versions - .into_iter() - .max() - .unwrap_or_else( - || { - semver::Version { - major: 0, - minor: 0, - patch: 0, - pre: vec![], - build: vec![], - } - } - ) + versions.into_iter().max().unwrap_or_else(|| { + semver::Version { + major: 0, + minor: 0, + patch: 0, + pre: vec![], + build: vec![], + } + }) } } impl NewVersion { pub fn new(crate_id: i32, num: &semver::Version, features: &HashMap>) -> CargoResult { let features = json::encode(features)?; - Ok( - NewVersion { - crate_id: crate_id, - num: num.to_string(), - features: features, - } - ) + Ok(NewVersion { + crate_id: crate_id, + num: num.to_string(), + features: features, + }) } pub fn save(&self, conn: &PgConnection, authors: &[String]) -> CargoResult { @@ -222,45 +211,40 @@ impl NewVersion { use diesel::expression::dsl::exists; use schema::versions::dsl::*; - let already_uploaded = versions - .filter(crate_id.eq(self.crate_id)) - .filter(num.eq(&self.num)); + let already_uploaded = versions.filter(crate_id.eq(self.crate_id)).filter( + num.eq(&self.num), + ); if select(exists(already_uploaded)).get_result(conn)? { - return Err( - human( - &format_args!("crate version `{}` is already \ - uploaded", self.num) - ) - ); + return Err(human(&format_args!( + "crate version `{}` is already \ + uploaded", + self.num + ))); } - conn.transaction( - || { - let version = insert(self).into(versions).get_result::(conn)?; - - let new_authors = authors - .iter() - .map( - |s| { - NewAuthor { - version_id: version.id, - name: &*s, - } - } - ) - .collect::>(); - - insert(&new_authors) - .into(version_authors::table) - .execute(conn)?; - Ok(version) - } - ) + conn.transaction(|| { + let version = insert(self).into(versions).get_result::(conn)?; + + let new_authors = authors + .iter() + .map(|s| { + NewAuthor { + version_id: version.id, + name: &*s, + } + }) + .collect::>(); + + insert(&new_authors).into(version_authors::table).execute( + conn, + )?; + Ok(version) + }) } } #[derive(Insertable)] -#[table_name="version_authors"] +#[table_name = "version_authors"] struct NewAuthor<'a> { version_id: i32, name: &'a str, @@ -270,9 +254,9 @@ impl Queryable for Version { type Row = (i32, i32, String, Timespec, Timespec, i32, Option, bool); fn build(row: Self::Row) -> Self { - let features = row.6 - .map(|s| json::decode(&s).unwrap()) - .unwrap_or_else(HashMap::new); + let features = row.6.map(|s| json::decode(&s).unwrap()).unwrap_or_else( + HashMap::new, + ); Version { id: row.0, crate_id: row.1, @@ -290,9 +274,9 @@ impl Model for Version { fn from_row(row: &Row) -> Version { let num: String = row.get("num"); let features: Option = row.get("features"); - let features = features - .map(|s| json::decode(&s).unwrap()) - .unwrap_or_else(HashMap::new); + let features = features.map(|s| json::decode(&s).unwrap()).unwrap_or_else( + HashMap::new, + ); Version { id: row.get("id"), crate_id: row.get("crate_id"), @@ -317,7 +301,11 @@ pub fn index(req: &mut Request) -> CargoResult { // Extract all ids requested. let query = url::form_urlencoded::parse(req.query_string().unwrap_or("").as_bytes()); let ids = query - .filter_map(|(ref a, ref b)| if *a == "ids[]" { b.parse().ok() } else { None }) + .filter_map(|(ref a, ref b)| if *a == "ids[]" { + b.parse().ok() + } else { + None + }) .collect::>(); // Load all versions @@ -326,13 +314,13 @@ pub fn index(req: &mut Request) -> CargoResult { let mut versions = Vec::new(); if !ids.is_empty() { let stmt = conn.prepare( - "\ + "\ SELECT versions.*, crates.name AS crate_name FROM versions LEFT JOIN crates ON crates.id = versions.crate_id WHERE versions.id = ANY($1) - " - )?; + ", + )?; for row in stmt.query(&[&ids])?.iter() { let v: Version = Model::from_row(&row); let crate_name: String = row.get("crate_name"); @@ -373,20 +361,19 @@ pub fn show(req: &mut Request) -> CargoResult { fn version_and_crate_old(req: &mut Request) -> CargoResult<(Version, Crate)> { let crate_name = &req.params()["crate_id"]; let semver = &req.params()["version"]; - let semver = semver::Version::parse(semver) - .map_err(|_| human(&format_args!("invalid semver: {}", semver)))?; + let semver = semver::Version::parse(semver).map_err(|_| { + human(&format_args!("invalid semver: {}", semver)) + })?; let tx = req.tx()?; let krate = Crate::find_by_name(tx, crate_name)?; let version = Version::find_by_num(tx, krate.id, &semver)?; - let version = version - .chain_error( - || { - human( - &format_args!("crate `{}` does not have a version `{}`", - crate_name, semver) - ) - } - )?; + let version = version.chain_error(|| { + human(&format_args!( + "crate `{}` does not have a version `{}`", + crate_name, + semver + )) + })?; Ok((version, krate)) } @@ -401,14 +388,13 @@ fn version_and_crate(req: &mut Request) -> CargoResult<(Version, Crate)> { let version = Version::belonging_to(&krate) .filter(versions::num.eq(semver)) .first(&*conn) - .map_err( - |_| { - human( - &format_args!("crate `{}` does not have a version `{}`", - crate_name, semver) - ) - } - )?; + .map_err(|_| { + human(&format_args!( + "crate `{}` does not have a version `{}`", + crate_name, + semver + )) + })?; Ok((version, krate)) } @@ -441,7 +427,10 @@ pub fn downloads(req: &mut Request) -> CargoResult { let cutoff_start_date = cutoff_end_date + Duration::days(-89); let downloads = VersionDownload::belonging_to(&version) - .filter(version_downloads::date.between(date(cutoff_start_date)..date(cutoff_end_date))) + .filter(version_downloads::date.between( + date(cutoff_start_date).. + date(cutoff_end_date), + )) .order(version_downloads::date) .load(&*conn)? .into_iter() @@ -473,14 +462,10 @@ pub fn authors(req: &mut Request) -> CargoResult { struct Meta { names: Vec, } - Ok( - req.json( - &R { - users: vec![], - meta: Meta { names: names }, - } - ) - ) + Ok(req.json(&R { + users: vec![], + meta: Meta { names: names }, + })) } /// Handles the `DELETE /crates/:crate_id/:version/yank` route. @@ -503,15 +488,13 @@ fn modify_yank(req: &mut Request, yanked: bool) -> CargoResult { } if version.yanked != yanked { - conn.transaction::<_, Box, _>( - || { - diesel::update(&version) - .set(versions::yanked.eq(yanked)) - .execute(&*conn)?; - git::yank(&**req.app(), &krate.name, &version.num, yanked)?; - Ok(()) - } - )?; + conn.transaction::<_, Box, _>(|| { + diesel::update(&version) + .set(versions::yanked.eq(yanked)) + .execute(&*conn)?; + git::yank(&**req.app(), &krate.name, &version.num, yanked)?; + Ok(()) + })?; } #[derive(RustcEncodable)] From 7b8f65e9c7f084a5763edce4ea8b2dde8b1c8878 Mon Sep 17 00:00:00 2001 From: Vignesh Date: Tue, 13 Jun 2017 23:38:48 +1000 Subject: [PATCH 09/14] cargo fmt --- src/util/hasher.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/util/hasher.rs b/src/util/hasher.rs index 52132eb2c2f..1dbc4d09b28 100644 --- a/src/util/hasher.rs +++ b/src/util/hasher.rs @@ -18,6 +18,9 @@ impl HashingReader { pub fn finalize(mut self) -> Vec { #[allow(deprecated)] #[allow(deprecated)] #[allow(deprecated)] +#[allow(deprecated)] #[allow(deprecated)] + #[allow(deprecated)] + #[allow(deprecated)] #[allow(deprecated)] self.hasher.finish().unwrap() } } From 2f30a73a7525612f1f6f0010dbb34fba59f1fcda Mon Sep 17 00:00:00 2001 From: Vignesh Date: Tue, 13 Jun 2017 23:57:26 +1000 Subject: [PATCH 10/14] Added rustfmt_skip to stop line merging --- src/util/hasher.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/util/hasher.rs b/src/util/hasher.rs index 1dbc4d09b28..f473501033d 100644 --- a/src/util/hasher.rs +++ b/src/util/hasher.rs @@ -16,12 +16,13 @@ impl HashingReader { } pub fn finalize(mut self) -> Vec { + /* + rustfmt wanted to merge the lines together so had to use this + to stop this from occurring + */ + #[rustfmt_skip] #[allow(deprecated)] -#[allow(deprecated)] #[allow(deprecated)] -#[allow(deprecated)] #[allow(deprecated)] - #[allow(deprecated)] - #[allow(deprecated)] - #[allow(deprecated)] self.hasher.finish().unwrap() + self.hasher.finish().unwrap() } } From a5ce993e3934eebd07fcb29008ab0cbf59eef616 Mon Sep 17 00:00:00 2001 From: Vignesh Date: Wed, 14 Jun 2017 00:25:28 +1000 Subject: [PATCH 11/14] Changed rustfmt_skip declaration --- src/util/hasher.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/hasher.rs b/src/util/hasher.rs index f473501033d..a81e19f8044 100644 --- a/src/util/hasher.rs +++ b/src/util/hasher.rs @@ -20,7 +20,7 @@ impl HashingReader { rustfmt wanted to merge the lines together so had to use this to stop this from occurring */ - #[rustfmt_skip] + #[cfg_attr(rustfmt, rustfmt_skip)] #[allow(deprecated)] self.hasher.finish().unwrap() } From 209dab0f40bbcaa7826188dd3d3ff85b72005ecd Mon Sep 17 00:00:00 2001 From: Vignesh Date: Wed, 14 Jun 2017 00:27:17 +1000 Subject: [PATCH 12/14] Added cargo caching --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 2c47e57ecdb..99c52f47ca5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ sudo: false dist: trusty cache: + cargo: true directories: - $HOME/.yarn-cache From c4533adc4050778b5a80109a31c78fc04757dfb3 Mon Sep 17 00:00:00 2001 From: Vignesh Date: Wed, 14 Jun 2017 00:32:31 +1000 Subject: [PATCH 13/14] Separated cargo fmt into separate check --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 99c52f47ca5..01423dc5073 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,6 +40,8 @@ matrix: - rust: stable script: - cargo fmt -- --write-mode=diff + - rust: stable + script: - cargo build - cargo test - yarn run test From 91898fa138f3348813449dede519cf4d7b800b24 Mon Sep 17 00:00:00 2001 From: Vignesh Date: Wed, 14 Jun 2017 00:32:44 +1000 Subject: [PATCH 14/14] Added note to use latest rustfmt --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9f21f26dee0..c8b3559fdfc 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,9 @@ frontend with a Rust backend, and there are many tasks appropriate for a variety of skill levels. The Rust backend uses rustfmt for code formatting, so ensure that you run it prior -to submitting a pull request. More information on setting up and running rustfmt can -be found [here](https://github.com/rust-lang-nursery/rustfmt/blob/master/README.md). +to submitting a pull request, and that your version of rustfmt is the latst version. +More information on setting up and running rustfmt can be found +[here](https://github.com/rust-lang-nursery/rustfmt/blob/master/README.md). Please see [docs/CONTRIBUTING.md](https://github.com/rust-lang/crates.io/blob/master/docs/CONTRIBUTING.md) for ideas about what to work on and how to set up a development environment.