diff --git a/.gitignore b/.gitignore index 9a569b66ceb..6a2bb03e674 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,5 @@ npm-debug.log testem.log .env +# rustfmt backup files +*.bk diff --git a/src/app.rs b/src/app.rs index 1922226533a..cee50a06fcc 100644 --- a/src/app.rs +++ b/src/app.rs @@ -32,23 +32,29 @@ 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")); let db_config = r2d2::Config::builder() - .pool_size(if config.env == ::Env::Production {10} else {1}) - .helper_threads(if config.env == ::Env::Production {3} else {1}) + .pool_size(if config.env == ::Env::Production { + 10 + } else { + 1 + }) + .helper_threads(if config.env == ::Env::Production { + 3 + } else { + 1 + }) .build(); let repo = git2::Repository::open(&config.git_repo_checkout).unwrap(); @@ -73,7 +79,7 @@ impl App { if let Some(ref proxy) = self.s3_proxy { handle.proxy(proxy).unwrap(); } - return handle + return handle; } } @@ -84,13 +90,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 } @@ -103,7 +111,8 @@ pub trait RequestApp { impl<'a> RequestApp for Request + 'a { fn app(&self) -> &Arc { - self.extensions().find::>() + self.extensions() + .find::>() .expect("Missing app") } } diff --git a/src/badge.rs b/src/badge.rs index 30dea5a8bee..d5d2652980b 100644 --- a/src/badge.rs +++ b/src/badge.rs @@ -10,13 +10,17 @@ use rustc_serialize::json::Json; #[derive(Debug, PartialEq, Clone)] pub enum Badge { TravisCi { - repository: String, branch: Option, + repository: String, + branch: Option, }, Appveyor { - repository: String, branch: Option, service: Option, + repository: String, + branch: Option, + service: Option, }, GitLab { - repository: String, branch: Option, + repository: String, + branch: Option, }, } @@ -35,57 +39,51 @@ impl Model for Badge { "travis-ci" => { Badge::TravisCi { branch: attributes.get("branch") - .and_then(Json::as_string) - .map(str::to_string), + .and_then(Json::as_string) + .map(str::to_string), repository: attributes.get("repository") - .and_then(Json::as_string) - .map(str::to_string) - .expect("Invalid TravisCi badge \ - without repository in the \ - database"), + .and_then(Json::as_string) + .map(str::to_string) + .expect("Invalid TravisCi badge without repository in the database"), } - }, + } "appveyor" => { Badge::Appveyor { service: attributes.get("service") - .and_then(Json::as_string) - .map(str::to_string), + .and_then(Json::as_string) + .map(str::to_string), branch: attributes.get("branch") - .and_then(Json::as_string) - .map(str::to_string), + .and_then(Json::as_string) + .map(str::to_string), repository: attributes.get("repository") - .and_then(Json::as_string) - .map(str::to_string) - .expect("Invalid Appveyor badge \ - without repository in the \ - database"), + .and_then(Json::as_string) + .map(str::to_string) + .expect("Invalid Appveyor badge without repository in the database"), } - }, + } "gitlab" => { Badge::GitLab { branch: attributes.get("branch") - .and_then(Json::as_string) - .map(str::to_string), + .and_then(Json::as_string) + .map(str::to_string), repository: attributes.get("repository") - .and_then(Json::as_string) - .map(str::to_string) - .expect("Invalid GitLab badge \ - without repository in the \ - database"), + .and_then(Json::as_string) + .map(str::to_string) + .expect("Invalid GitLab badge without repository in the database"), } - }, + } _ => { panic!("Unknown badge type {} in the database", badge_type); - }, + } } } else { - panic!( - "badge attributes {:?} in the database was not a JSON object", - attributes - ); + panic!("badge attributes {:?} in the database was not a JSON object", + attributes); } } - fn table_name(_: Option) -> &'static str { "badges" } + fn table_name(_: Option) -> &'static str { + "badges" + } } impl Badge { @@ -98,16 +96,17 @@ impl Badge { pub fn badge_type(&self) -> &'static str { match *self { - Badge::TravisCi {..} => "travis-ci", - Badge::Appveyor {..} => "appveyor", - Badge::GitLab{..} => "gitlab", + Badge::TravisCi { .. } => "travis-ci", + Badge::Appveyor { .. } => "appveyor", + Badge::GitLab { .. } => "gitlab", } } pub fn json_attributes(self) -> Json { - Json::Object(self.attributes().into_iter().map(|(k, v)| { - (k, Json::String(v)) - }).collect()) + Json::Object(self.attributes() + .into_iter() + .map(|(k, v)| (k, Json::String(v))) + .collect()) } fn attributes(self) -> HashMap { @@ -117,36 +116,24 @@ impl Badge { Badge::TravisCi { branch, repository } => { attributes.insert(String::from("repository"), repository); if let Some(branch) = branch { - attributes.insert( - String::from("branch"), - branch - ); + attributes.insert(String::from("branch"), branch); } - }, + } Badge::Appveyor { service, branch, repository } => { attributes.insert(String::from("repository"), repository); if let Some(branch) = branch { - attributes.insert( - String::from("branch"), - branch - ); + attributes.insert(String::from("branch"), branch); } if let Some(service) = service { - attributes.insert( - String::from("service"), - service - ); + attributes.insert(String::from("service"), service); } - }, + } Badge::GitLab { branch, repository } => { attributes.insert(String::from("repository"), repository); if let Some(branch) = branch { - attributes.insert( - String::from("branch"), - branch - ); + attributes.insert(String::from("branch"), branch); } - }, + } } attributes @@ -162,40 +149,39 @@ impl Badge { Ok(Badge::TravisCi { repository: repository.to_string(), branch: attributes.get("branch") - .map(String::to_string), + .map(String::to_string), }) - }, + } None => Err(badge_type.to_string()), } - }, + } "appveyor" => { match attributes.get("repository") { Some(repository) => { Ok(Badge::Appveyor { repository: repository.to_string(), branch: attributes.get("branch") - .map(String::to_string), + .map(String::to_string), service: attributes.get("service") - .map(String::to_string), - + .map(String::to_string), }) - }, + } None => Err(badge_type.to_string()), } - }, + } "gitlab" => { match attributes.get("repository") { Some(repository) => { Ok(Badge::GitLab { repository: repository.to_string(), branch: attributes.get("branch") - .map(String::to_string), + .map(String::to_string), }) - }, + } None => Err(badge_type.to_string()), } - }, - _ => Err(badge_type.to_string()), + } + _ => Err(badge_type.to_string()), } } @@ -206,17 +192,18 @@ impl Badge { let mut invalid_badges = vec![]; - let badges: Vec<_> = badges.iter().filter_map(|(k, v)| { - Badge::from_attributes(k, v).map_err(|invalid_badge| { - invalid_badges.push(invalid_badge) - }).ok() - }).collect(); + let badges: Vec<_> = badges.iter() + .filter_map(|(k, v)| { + Badge::from_attributes(k, v) + .map_err(|invalid_badge| invalid_badges.push(invalid_badge)) + .ok() + }) + .collect(); conn.execute("\ DELETE FROM badges \ WHERE crate_id = $1;", - &[&krate.id] - )?; + &[&krate.id])?; for badge in badges { conn.execute("\ @@ -224,8 +211,7 @@ impl Badge { VALUES ($1, $2, $3) \ ON CONFLICT (crate_id, badge_type) DO UPDATE \ SET attributes = EXCLUDED.attributes;", - &[&krate.id, &badge.badge_type(), &badge.json_attributes()] - )?; + &[&krate.id, &badge.badge_type(), &badge.json_attributes()])?; } Ok(invalid_badges) } diff --git a/src/bin/delete-crate.rs b/src/bin/delete-crate.rs index 639f0628024..330f96694aa 100644 --- a/src/bin/delete-crate.rs +++ b/src/bin/delete-crate.rs @@ -31,62 +31,75 @@ 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!("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 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..3ca6e93199a 100644 --- a/src/bin/delete-version.rs +++ b/src/bin/delete-version.rs @@ -31,40 +31,54 @@ 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, + 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 401877e7a16..fa5609c307f 100644 --- a/src/bin/fill-in-user-id.rs +++ b/src/bin/fill-in-user-id.rs @@ -71,7 +71,7 @@ fn update(app: &App, tx: &postgres::transaction::Transaction) { let ghuser: GithubUser = try!(http::parse_github_response(handle, resp)); if let Some(ref avatar) = avatar { if !avatar.contains(&ghuser.id.to_string()) { - return Err(human(format!("avatar: {}", avatar))) + return Err(human(format!("avatar: {}", avatar))); } } if ghuser.login == login { @@ -87,4 +87,3 @@ fn update(app: &App, tx: &postgres::transaction::Transaction) { } } } - diff --git a/src/bin/migrate.rs b/src/bin/migrate.rs index ce635d3db5a..f0a2032355b 100644 --- a/src/bin/migrate.rs +++ b/src/bin/migrate.rs @@ -25,7 +25,8 @@ fn main() { } fn apply(tx: postgres::transaction::Transaction, - migrations: Vec) -> postgres::Result<()> { + migrations: Vec) + -> postgres::Result<()> { let mut mgr = try!(migrate::Manager::new(tx)); for m in migrations.into_iter() { try!(mgr.apply(m)); @@ -35,12 +36,13 @@ fn apply(tx: postgres::transaction::Transaction, } fn rollback(tx: postgres::transaction::Transaction, - migrations: Vec) -> postgres::Result<()> { + migrations: Vec) + -> postgres::Result<()> { let mut mgr = try!(migrate::Manager::new(tx)); for m in migrations.into_iter().rev() { if mgr.contains(m.version()) { try!(mgr.rollback(m)); - break + break; } } mgr.set_commit(); @@ -48,89 +50,139 @@ fn rollback(tx: postgres::transaction::Transaction, } fn migrations() -> Vec { - let migrations = vec![ - Migration::add_table(20140924113530, "users", " + let migrations = + vec![Migration::add_table(20140924113530, + "users", + " id SERIAL PRIMARY KEY, - email VARCHAR NOT NULL UNIQUE, - gh_access_token VARCHAR NOT NULL, - api_token VARCHAR NOT NULL + \ + email VARCHAR NOT NULL UNIQUE, + \ + gh_access_token VARCHAR NOT NULL, + api_token \ + VARCHAR NOT NULL "), - Migration::add_table(20140924114003, "packages", " + Migration::add_table(20140924114003, + "packages", + " id SERIAL PRIMARY KEY, - name VARCHAR NOT NULL UNIQUE, - user_id INTEGER NOT NULL + \ + name VARCHAR NOT NULL UNIQUE, + user_id \ + INTEGER NOT NULL "), - Migration::add_table(20140924114059, "versions", " + Migration::add_table(20140924114059, + "versions", + " id SERIAL PRIMARY KEY, - package_id INTEGER NOT NULL, - num VARCHAR NOT NULL + \ + package_id INTEGER NOT NULL, + num \ + VARCHAR NOT NULL "), - Migration::run(20140924115329, - &format!("ALTER TABLE versions ADD CONSTRAINT \ - unique_num UNIQUE (package_id, num)"), - &format!("ALTER TABLE versions DROP CONSTRAINT \ - unique_num")), - Migration::add_table(20140924120803, "version_dependencies", " + Migration::run(20140924115329, + &format!("ALTER TABLE versions ADD CONSTRAINT unique_num UNIQUE \ + (package_id, num)"), + &format!("ALTER TABLE versions DROP CONSTRAINT unique_num")), + Migration::add_table(20140924120803, + "version_dependencies", + " version_id INTEGER NOT NULL, - depends_on_id INTEGER NOT NULL + \ + depends_on_id INTEGER NOT NULL "), - Migration::add_column(20140925132248, "packages", "updated_at", - "TIMESTAMP NOT NULL DEFAULT now()"), - Migration::add_column(20140925132249, "packages", "created_at", - "TIMESTAMP NOT NULL DEFAULT now()"), - Migration::new(20140925132250, |tx| { + Migration::add_column(20140925132248, + "packages", + "updated_at", + "TIMESTAMP NOT NULL DEFAULT now()"), + Migration::add_column(20140925132249, + "packages", + "created_at", + "TIMESTAMP NOT NULL DEFAULT now()"), + Migration::new(20140925132250, + |tx| { try!(tx.execute("UPDATE packages SET updated_at = now() \ - WHERE updated_at IS NULL", &[])); + WHERE updated_at IS NULL", + &[])); try!(tx.execute("UPDATE packages SET created_at = now() \ - WHERE created_at IS NULL", &[])); + WHERE created_at IS NULL", + &[])); Ok(()) - }, |_| Ok(())), - Migration::add_column(20140925132251, "versions", "updated_at", - "TIMESTAMP NOT NULL DEFAULT now()"), - Migration::add_column(20140925132252, "versions", "created_at", - "TIMESTAMP NOT NULL DEFAULT now()"), - Migration::new(20140925132253, |tx| { + }, + |_| Ok(())), + Migration::add_column(20140925132251, + "versions", + "updated_at", + "TIMESTAMP NOT NULL DEFAULT now()"), + Migration::add_column(20140925132252, + "versions", + "created_at", + "TIMESTAMP NOT NULL DEFAULT now()"), + Migration::new(20140925132253, + |tx| { try!(tx.execute("UPDATE versions SET updated_at = now() \ - WHERE updated_at IS NULL", &[])); + WHERE updated_at IS NULL", + &[])); try!(tx.execute("UPDATE versions SET created_at = now() \ - WHERE created_at IS NULL", &[])); + WHERE created_at IS NULL", + &[])); Ok(()) - }, |_| Ok(())), - Migration::new(20140925132254, |tx| { + }, + |_| Ok(())), + Migration::new(20140925132254, + |tx| { try!(tx.execute("ALTER TABLE versions ALTER COLUMN updated_at \ - DROP DEFAULT", &[])); + DROP DEFAULT", + &[])); try!(tx.execute("ALTER TABLE versions ALTER COLUMN created_at \ - DROP DEFAULT", &[])); + DROP DEFAULT", + &[])); try!(tx.execute("ALTER TABLE packages ALTER COLUMN updated_at \ - DROP DEFAULT", &[])); + DROP DEFAULT", + &[])); try!(tx.execute("ALTER TABLE packages ALTER COLUMN created_at \ - DROP DEFAULT", &[])); + DROP DEFAULT", + &[])); Ok(()) - }, |_| Ok(())), - Migration::add_table(20140925153704, "metadata", " + }, + |_| Ok(())), + Migration::add_table(20140925153704, + "metadata", + " total_downloads BIGINT NOT NULL "), - Migration::new(20140925153705, |tx| { - try!(tx.execute("INSERT INTO metadata (total_downloads) \ + Migration::new(20140925153705, + |tx| { + try!(tx.execute("INSERT INTO metadata (total_downloads) \ VALUES ($1)", &[&0i64])); - Ok(()) - }, |tx| { - try!(tx.execute("DELETE FROM metadata", &[])); Ok(()) - }), - Migration::add_column(20140925161623, "packages", "downloads", - "INTEGER NOT NULL DEFAULT 0"), - Migration::add_column(20140925161624, "versions", "downloads", - "INTEGER NOT NULL DEFAULT 0"), - Migration::new(20140925161625, |tx| { + Ok(()) + }, + |tx| { + try!(tx.execute("DELETE FROM metadata", &[])); + Ok(()) + }), + Migration::add_column(20140925161623, + "packages", + "downloads", + "INTEGER NOT NULL DEFAULT 0"), + Migration::add_column(20140925161624, + "versions", + "downloads", + "INTEGER NOT NULL DEFAULT 0"), + Migration::new(20140925161625, + |tx| { try!(tx.execute("ALTER TABLE versions ALTER COLUMN downloads \ - DROP DEFAULT", &[])); + DROP DEFAULT", + &[])); try!(tx.execute("ALTER TABLE packages ALTER COLUMN downloads \ - DROP DEFAULT", &[])); + DROP DEFAULT", + &[])); Ok(()) - }, |_| Ok(())), - Migration::add_column(20140926130044, "packages", "max_version", - "VARCHAR"), - Migration::new(20140926130045, |tx| { + }, + |_| Ok(())), + Migration::add_column(20140926130044, "packages", "max_version", "VARCHAR"), + Migration::new(20140926130045, + |tx| { let stmt = try!(tx.prepare("SELECT * FROM packages")); let rows = try!(stmt.query(&[])); for row in rows.iter() { @@ -143,193 +195,243 @@ fn migrations() -> Vec { &[&max, &pkg.id])); } Ok(()) - }, |_| Ok(())), - Migration::new(20140926130046, |tx| { - try!(tx.execute("ALTER TABLE versions ALTER COLUMN downloads \ - SET NOT NULL", &[])); - Ok(()) - }, |tx| { - try!(tx.execute("ALTER TABLE versions ALTER COLUMN downloads \ - DROP NOT NULL", &[])); - Ok(()) - }), - Migration::new(20140926174020, |tx| { + }, + |_| Ok(())), + Migration::new(20140926130046, + |tx| { + try!(tx.execute("ALTER TABLE versions ALTER COLUMN downloads \ + SET NOT NULL", + &[])); + Ok(()) + }, + |tx| { + try!(tx.execute("ALTER TABLE versions ALTER COLUMN downloads DROP \ + NOT NULL", + &[])); + Ok(()) + }), + Migration::new(20140926174020, + |tx| { try!(tx.execute("ALTER TABLE packages RENAME TO crates", &[])); try!(tx.execute("ALTER TABLE versions RENAME COLUMN package_id \ - TO crate_id", &[])); + TO crate_id", + &[])); Ok(()) - }, |tx| { + }, + |tx| { try!(tx.execute("ALTER TABLE crates RENAME TO packages", &[])); try!(tx.execute("ALTER TABLE versions RENAME COLUMN crate_id \ - TO package_id", &[])); + TO package_id", + &[])); Ok(()) }), - Migration::run(20140929103749, - "CREATE INDEX index_crate_updated_at ON crates (updated_at)", - "DROP INDEX index_crate_updated_at"), - Migration::run(20140929103750, - "CREATE INDEX index_crate_created_at ON crates (created_at)", - "DROP INDEX index_crate_created_at"), - Migration::run(20140929103751, - "CREATE INDEX index_crate_downloads ON crates (downloads)", - "DROP INDEX index_crate_downloads"), - Migration::run(20140929103752, - "CREATE INDEX index_version_crate_id ON versions (crate_id)", - "DROP INDEX index_version_crate_id"), - Migration::run(20140929103753, - "CREATE INDEX index_version_num ON versions (num)", - "DROP INDEX index_version_num"), - Migration::run(20140929103754, - "CREATE INDEX index_version_dependencies_version_id \ - ON version_dependencies (version_id)", - "DROP INDEX index_version_dependencies_version_id"), - Migration::run(20140929103755, - "CREATE INDEX index_version_dependencies_depends_on_id \ - ON version_dependencies (depends_on_id)", - "DROP INDEX index_version_dependencies_depends_on_id"), - Migration::add_table(20140929103756, "crate_downloads", " + Migration::run(20140929103749, + "CREATE INDEX index_crate_updated_at ON crates (updated_at)", + "DROP INDEX index_crate_updated_at"), + Migration::run(20140929103750, + "CREATE INDEX index_crate_created_at ON crates (created_at)", + "DROP INDEX index_crate_created_at"), + Migration::run(20140929103751, + "CREATE INDEX index_crate_downloads ON crates (downloads)", + "DROP INDEX index_crate_downloads"), + Migration::run(20140929103752, + "CREATE INDEX index_version_crate_id ON versions (crate_id)", + "DROP INDEX index_version_crate_id"), + Migration::run(20140929103753, + "CREATE INDEX index_version_num ON versions (num)", + "DROP INDEX index_version_num"), + Migration::run(20140929103754, + "CREATE INDEX index_version_dependencies_version_id ON \ + version_dependencies (version_id)", + "DROP INDEX index_version_dependencies_version_id"), + Migration::run(20140929103755, + "CREATE INDEX index_version_dependencies_depends_on_id ON \ + version_dependencies (depends_on_id)", + "DROP INDEX index_version_dependencies_depends_on_id"), + Migration::add_table(20140929103756, + "crate_downloads", + " id SERIAL PRIMARY KEY, - crate_id INTEGER NOT NULL, - downloads INTEGER NOT NULL, - date TIMESTAMP NOT NULL + \ + crate_id INTEGER NOT NULL, + downloads \ + INTEGER NOT NULL, + date TIMESTAMP NOT \ + NULL "), - Migration::run(20140929103757, - "CREATE INDEX index_crate_downloads_crate_id \ - ON crate_downloads (crate_id)", - "DROP INDEX index_crate_downloads_crate_id"), - Migration::run(20140929103758, - "CREATE INDEX index_crate_downloads_date \ - ON crate_downloads (date(date))", - "DROP INDEX index_crate_downloads_date"), - Migration::add_table(20140929103759, "version_downloads", " + Migration::run(20140929103757, + "CREATE INDEX index_crate_downloads_crate_id ON crate_downloads \ + (crate_id)", + "DROP INDEX index_crate_downloads_crate_id"), + Migration::run(20140929103758, + "CREATE INDEX index_crate_downloads_date ON crate_downloads \ + (date(date))", + "DROP INDEX index_crate_downloads_date"), + Migration::add_table(20140929103759, + "version_downloads", + " id SERIAL PRIMARY KEY, - version_id INTEGER NOT NULL, - downloads INTEGER NOT NULL, - counted INTEGER NOT NULL, + \ + version_id INTEGER NOT NULL, + downloads \ + INTEGER NOT NULL, + counted INTEGER NOT \ + NULL, date TIMESTAMP NOT NULL, - processed BOOLEAN NOT NULL + \ + processed BOOLEAN NOT NULL "), - Migration::run(20140929103760, - "CREATE INDEX index_version_downloads_version_id \ - ON version_downloads (version_id)", - "DROP INDEX index_version_downloads_version_id"), - Migration::run(20140929103761, - "CREATE INDEX index_version_downloads_date \ - ON version_downloads (date(date))", - "DROP INDEX index_version_downloads_date"), - Migration::run(20140929103763, - "CREATE INDEX index_version_downloads_processed \ - ON version_downloads (processed) - WHERE processed = FALSE", - "DROP INDEX index_version_downloads_processed"), - Migration::run(20140929185718, - "CREATE INDEX index_crates_name_search \ - ON crates USING gin(to_tsvector('english', name))", - "DROP INDEX index_crates_name_search"), - Migration::run(20140930082104, - "DROP TABLE version_dependencies", - "CREATE TABLE version_dependencies ( - version_id INTEGER + Migration::run(20140929103760, + "CREATE INDEX index_version_downloads_version_id ON \ + version_downloads (version_id)", + "DROP INDEX index_version_downloads_version_id"), + Migration::run(20140929103761, + "CREATE INDEX index_version_downloads_date ON version_downloads \ + (date(date))", + "DROP INDEX index_version_downloads_date"), + Migration::run(20140929103763, + "CREATE INDEX index_version_downloads_processed ON \ + version_downloads (processed) + WHERE \ + processed = FALSE", + "DROP INDEX index_version_downloads_processed"), + Migration::run(20140929185718, + "CREATE INDEX index_crates_name_search ON crates USING \ + gin(to_tsvector('english', name))", + "DROP INDEX index_crates_name_search"), + Migration::run(20140930082104, + "DROP TABLE version_dependencies", + "CREATE TABLE version_dependencies ( + \ + version_id INTEGER )"), - Migration::add_table(20140930082105, "dependencies", " + Migration::add_table(20140930082105, + "dependencies", + " id SERIAL PRIMARY KEY, - version_id INTEGER NOT NULL, - crate_id INTEGER NOT NULL, - req VARCHAR NOT NULL, + \ + version_id INTEGER NOT NULL, + crate_id \ + INTEGER NOT NULL, + req VARCHAR NOT \ + NULL, optional BOOLEAN NOT NULL, - default_features BOOLEAN NOT NULL, - features VARCHAR NOT NULL + \ + default_features BOOLEAN NOT NULL, + features \ + VARCHAR NOT NULL "), - Migration::add_column(20140930085441, "versions", "features", - "VARCHAR"), - Migration::run(20140930203145, - "CREATE INDEX index_dependencies_version_id \ - ON dependencies (version_id)", - "DROP INDEX index_dependencies_version_id"), - Migration::run(20140930203146, - "CREATE INDEX index_dependencies_crate_id \ - ON dependencies (crate_id)", - "DROP INDEX index_dependencies_crate_id"), - Migration::add_column(20141001190227, "users", "gh_login", - "VARCHAR NOT NULL"), - Migration::add_column(20141001190228, "users", "name", "VARCHAR"), - Migration::run(20141001190229, - "CREATE INDEX index_users_gh_login \ - ON users (gh_login)", - "DROP INDEX index_users_gh_login"), - Migration::run(20141001190230, - "ALTER TABLE users ALTER COLUMN email DROP NOT NULL", - "ALTER TABLE users ALTER COLUMN email SET NOT NULL"), - Migration::add_column(20141001190231, "users", "gh_avatar", "VARCHAR"), - Migration::run(20141002195939, - "CREATE INDEX index_crates_user_id \ - ON crates (user_id)", - "DROP INDEX index_crates_user_id"), - Migration::add_table(20141002195940, "follows", " + Migration::add_column(20140930085441, "versions", "features", "VARCHAR"), + Migration::run(20140930203145, + "CREATE INDEX index_dependencies_version_id ON dependencies \ + (version_id)", + "DROP INDEX index_dependencies_version_id"), + Migration::run(20140930203146, + "CREATE INDEX index_dependencies_crate_id ON dependencies (crate_id)", + "DROP INDEX index_dependencies_crate_id"), + Migration::add_column(20141001190227, "users", "gh_login", "VARCHAR NOT NULL"), + Migration::add_column(20141001190228, "users", "name", "VARCHAR"), + Migration::run(20141001190229, + "CREATE INDEX index_users_gh_login ON users (gh_login)", + "DROP INDEX index_users_gh_login"), + Migration::run(20141001190230, + "ALTER TABLE users ALTER COLUMN email DROP NOT NULL", + "ALTER TABLE users ALTER COLUMN email SET NOT NULL"), + Migration::add_column(20141001190231, "users", "gh_avatar", "VARCHAR"), + Migration::run(20141002195939, + "CREATE INDEX index_crates_user_id ON crates (user_id)", + "DROP INDEX index_crates_user_id"), + Migration::add_table(20141002195940, + "follows", + " user_id INTEGER NOT NULL, - crate_id INTEGER NOT NULL + \ + crate_id INTEGER NOT NULL "), - Migration::run(20141002195941, - "CREATE INDEX index_follows_user_id \ - ON follows (user_id)", - "DROP INDEX index_follows_user_id"), - foreign_key(20141002222426, "crate_downloads", "crate_id", "crates (id)"), - foreign_key(20141002222427, "crates", "user_id", "users (id)"), - foreign_key(20141002222428, "dependencies", "version_id", "versions (id)"), - foreign_key(20141002222429, "dependencies", "crate_id", "crates (id)"), - foreign_key(20141002222430, "follows", "crate_id", "crates (id)"), - foreign_key(20141002222431, "version_downloads", "version_id", - "versions (id)"), - foreign_key(20141002222432, "versions", "crate_id", "crates (id)"), - foreign_key(20141002222433, "follows", "user_id", "users (id)"), - Migration::add_table(20141007131146, "version_authors", " + Migration::run(20141002195941, + "CREATE INDEX index_follows_user_id ON follows (user_id)", + "DROP INDEX index_follows_user_id"), + foreign_key(20141002222426, "crate_downloads", "crate_id", "crates (id)"), + foreign_key(20141002222427, "crates", "user_id", "users (id)"), + foreign_key(20141002222428, + "dependencies", + "version_id", + "versions (id)"), + foreign_key(20141002222429, "dependencies", "crate_id", "crates (id)"), + foreign_key(20141002222430, "follows", "crate_id", "crates (id)"), + foreign_key(20141002222431, + "version_downloads", + "version_id", + "versions (id)"), + foreign_key(20141002222432, "versions", "crate_id", "crates (id)"), + foreign_key(20141002222433, "follows", "user_id", "users (id)"), + Migration::add_table(20141007131146, + "version_authors", + " id SERIAL PRIMARY KEY, - version_id INTEGER NOT NULL, - user_id INTEGER, + \ + version_id INTEGER NOT NULL, + user_id \ + INTEGER, name VARCHAR NOT NULL - "), - foreign_key(20141007131147, "version_authors", "user_id", "users (id)"), - foreign_key(20141007131148, "version_authors", "version_id", "versions (id)"), - index(20141007131149, "version_authors", "version_id"), + \ + "), + foreign_key(20141007131147, "version_authors", "user_id", "users (id)"), + foreign_key(20141007131148, + "version_authors", + "version_id", + "versions (id)"), + index(20141007131149, "version_authors", "version_id"), - Migration::add_table(20141007131735, "crate_owners", " + Migration::add_table(20141007131735, + "crate_owners", + " id SERIAL PRIMARY KEY, - crate_id INTEGER NOT NULL, - user_id INTEGER NOT NULL, - created_at TIMESTAMP NOT NULL, + \ + crate_id INTEGER NOT NULL, + user_id \ + INTEGER NOT NULL, + created_at TIMESTAMP NOT \ + NULL, created_by INTEGER "), - foreign_key(20141007131736, "crate_owners", "user_id", "users (id)"), - foreign_key(20141007131737, "crate_owners", "created_by", "users (id)"), - foreign_key(20141007131738, "crate_owners", "crate_id", "crates (id)"), - index(20141007131739, "crate_owners", "crate_id"), - Migration::add_column(20141007131740, "crate_owners", "deleted", - "BOOLEAN NOT NULL"), - Migration::add_column(20141007131741, "crate_owners", "updated_at", - "TIMESTAMP NOT NULL"), - Migration::add_column(20141007171515, "crates", "description", - "VARCHAR"), - Migration::add_column(20141007171516, "crates", "homepage", - "VARCHAR"), - Migration::add_column(20141007171517, "crates", "documentation", - "VARCHAR"), - Migration::add_column(20141010150327, "crates", "readme", "VARCHAR"), - Migration::add_column(20141013115510, "versions", "yanked", - "BOOLEAN DEFAULT FALSE"), - Migration::add_column(20141020175647, "crates", - "textsearchable_index_col", "tsvector"), - Migration::run(20141020175648, - "DROP INDEX index_crates_name_search", - "CREATE INDEX index_crates_name_search \ - ON crates USING gin(to_tsvector('english', name))"), - Migration::run(20141020175649, - "CREATE INDEX index_crates_name_search \ - ON crates USING gin(textsearchable_index_col)", - "DROP INDEX index_crates_name_search"), - - // http://www.postgresql.org/docs/8.3/static/textsearch-controls.html - // http://www.postgresql.org/docs/8.3/static/textsearch-features.html - Migration::new(20141020175650, |tx| { + foreign_key(20141007131736, "crate_owners", "user_id", "users (id)"), + foreign_key(20141007131737, "crate_owners", "created_by", "users (id)"), + foreign_key(20141007131738, "crate_owners", "crate_id", "crates (id)"), + index(20141007131739, "crate_owners", "crate_id"), + Migration::add_column(20141007131740, + "crate_owners", + "deleted", + "BOOLEAN NOT NULL"), + Migration::add_column(20141007131741, + "crate_owners", + "updated_at", + "TIMESTAMP NOT NULL"), + Migration::add_column(20141007171515, "crates", "description", "VARCHAR"), + Migration::add_column(20141007171516, "crates", "homepage", "VARCHAR"), + Migration::add_column(20141007171517, "crates", "documentation", "VARCHAR"), + Migration::add_column(20141010150327, "crates", "readme", "VARCHAR"), + Migration::add_column(20141013115510, + "versions", + "yanked", + "BOOLEAN DEFAULT FALSE"), + Migration::add_column(20141020175647, + "crates", + "textsearchable_index_col", + "tsvector"), + Migration::run(20141020175648, + "DROP INDEX index_crates_name_search", + "CREATE INDEX index_crates_name_search ON crates USING \ + gin(to_tsvector('english', name))"), + Migration::run(20141020175649, + "CREATE INDEX index_crates_name_search ON crates USING \ + gin(textsearchable_index_col)", + "DROP INDEX index_crates_name_search"), + + // http://www.postgresql.org/docs/8.3/static/textsearch-controls.html + // http://www.postgresql.org/docs/8.3/static/textsearch-features.html + Migration::new(20141020175650, + |tx| { try!(tx.batch_execute(" CREATE FUNCTION trigger_crates_name_search() RETURNS trigger AS $$ begin @@ -352,132 +454,180 @@ fn migrations() -> Vec { ")); Ok(()) - }, |tx| { + }, + |tx| { try!(tx.execute("DROP TRIGGER trigger_crates_tsvector_update - ON crates", &[])); + ON crates", + &[])); try!(tx.execute("DROP FUNCTION trigger_crates_name_search()", &[])); Ok(()) }), - Migration::add_column(20141020175651, "crates", "keywords", "varchar"), - Migration::add_table(20141021103503, "keywords", " + Migration::add_column(20141020175651, "crates", "keywords", "varchar"), + Migration::add_table(20141021103503, + "keywords", + " id SERIAL PRIMARY KEY, - keyword VARCHAR NOT NULL UNIQUE, - crates_cnt INTEGER NOT NULL, - created_at TIMESTAMP NOT NULL + \ + keyword VARCHAR NOT NULL UNIQUE, + \ + crates_cnt INTEGER NOT NULL, + created_at \ + TIMESTAMP NOT NULL "), - Migration::add_table(20141021103504, "crates_keywords", " + Migration::add_table(20141021103504, + "crates_keywords", + " crate_id INTEGER NOT NULL, - keyword_id INTEGER NOT NULL + \ + keyword_id INTEGER NOT NULL "), - foreign_key(20141021103505, "crates_keywords", "crate_id", "crates (id)"), - foreign_key(20141021103506, "crates_keywords", "keyword_id", - "keywords (id)"), - index(20141021103507, "crates_keywords", "crate_id"), - index(20141021103508, "crates_keywords", "keyword_id"), - index(20141021103509, "keywords", "keyword"), - index(20141021103510, "keywords", "crates_cnt"), - Migration::add_column(20141022110441, "dependencies", "target", "varchar"), - Migration::add_column(20141023180230, "crates", "license", "varchar"), - Migration::add_column(20141023180231, "crates", "repository", "varchar"), - - Migration::new(20141112082527, |tx| { + foreign_key(20141021103505, "crates_keywords", "crate_id", "crates (id)"), + foreign_key(20141021103506, + "crates_keywords", + "keyword_id", + "keywords (id)"), + index(20141021103507, "crates_keywords", "crate_id"), + index(20141021103508, "crates_keywords", "keyword_id"), + index(20141021103509, "keywords", "keyword"), + index(20141021103510, "keywords", "crates_cnt"), + Migration::add_column(20141022110441, "dependencies", "target", "varchar"), + Migration::add_column(20141023180230, "crates", "license", "varchar"), + Migration::add_column(20141023180231, "crates", "repository", "varchar"), + + Migration::new(20141112082527, + |tx| { try!(tx.execute("ALTER TABLE users DROP CONSTRAINT IF \ - EXISTS users_email_key", &[])); + EXISTS users_email_key", + &[])); Ok(()) - }, |_| Ok(())), - Migration::add_column(20141120162357, "dependencies", "kind", "INTEGER"), - Migration::new(20141121191309, |tx| { + }, + |_| Ok(())), + Migration::add_column(20141120162357, "dependencies", "kind", "INTEGER"), + Migration::new(20141121191309, + |tx| { try!(tx.execute("ALTER TABLE crates DROP CONSTRAINT \ - packages_name_key", &[])); + packages_name_key", + &[])); try!(tx.execute("CREATE UNIQUE INDEX index_crates_name \ - ON crates (lower(name))", &[])); + ON crates (lower(name))", + &[])); Ok(()) - }, |tx| { + }, + |tx| { try!(tx.execute("DROP INDEX index_crates_name", &[])); try!(tx.execute("ALTER TABLE crates ADD CONSTRAINT packages_name_key \ - UNIQUE (name)", &[])); + UNIQUE (name)", + &[])); Ok(()) }), - Migration::new(20150209202206, |tx| { + Migration::new(20150209202206, + |tx| { try!(fix_duplicate_crate_owners(tx)); try!(tx.execute("ALTER TABLE crate_owners ADD CONSTRAINT \ crate_owners_unique_user_per_crate \ - UNIQUE (user_id, crate_id)", &[])); - Ok(()) - }, |tx| { - try!(tx.execute("ALTER TABLE crate_owners DROP CONSTRAINT \ - crate_owners_unique_user_per_crate", &[])); + UNIQUE (user_id, crate_id)", + &[])); Ok(()) - }), - Migration::new(20150319224700, |tx| { + }, + |tx| { + try!(tx.execute("ALTER TABLE crate_owners DROP CONSTRAINT \ + crate_owners_unique_user_per_crate", + &[])); + Ok(()) + }), + Migration::new(20150319224700, + |tx| { try!(tx.execute(" CREATE FUNCTION canon_crate_name(text) RETURNS text AS $$ SELECT replace(lower($1), '-', '_') $$ LANGUAGE SQL - ", &[])); - Ok(()) - }, |tx| { - try!(tx.execute("DROP FUNCTION canon_crate_name(text)", &[])); + ", + &[])); Ok(()) - }), - Migration::new(20150319224701, |tx| { + }, + |tx| { + try!(tx.execute("DROP FUNCTION canon_crate_name(text)", &[])); + Ok(()) + }), + Migration::new(20150319224701, + |tx| { try!(tx.execute("DROP INDEX index_crates_name", &[])); try!(tx.execute("CREATE UNIQUE INDEX index_crates_name \ - ON crates (canon_crate_name(name))", &[])); + ON crates (canon_crate_name(name))", + &[])); Ok(()) - }, |tx| { + }, + |tx| { try!(tx.execute("DROP INDEX index_crates_name", &[])); try!(tx.execute("CREATE UNIQUE INDEX index_crates_name \ - ON crates (lower(name))", &[])); - Ok(()) - }), - Migration::new(20150320174400, |tx| { - try!(tx.execute("CREATE INDEX index_keywords_lower_keyword ON keywords (lower(keyword))", + ON crates (lower(name))", &[])); Ok(()) - }, |tx| { - try!(tx.execute("DROP INDEX index_keywords_lower_keyword", &[])); - Ok(()) }), - Migration::add_column(20150715170350, "crate_owners", "owner_kind", - "INTEGER NOT NULL DEFAULT 0"), - Migration::run(20150804170127, - "ALTER TABLE crate_owners ALTER owner_kind DROP DEFAULT", - "ALTER TABLE crate_owners ALTER owner_kind SET DEFAULT 0", - ), - Migration::add_table(20150804170128, "teams", " + Migration::new(20150320174400, + |tx| { + try!(tx.execute("CREATE INDEX index_keywords_lower_keyword ON \ + keywords (lower(keyword))", + &[])); + Ok(()) + }, + |tx| { + try!(tx.execute("DROP INDEX index_keywords_lower_keyword", &[])); + Ok(()) + }), + Migration::add_column(20150715170350, + "crate_owners", + "owner_kind", + "INTEGER NOT NULL DEFAULT 0"), + Migration::run(20150804170127, + "ALTER TABLE crate_owners ALTER owner_kind DROP DEFAULT", + "ALTER TABLE crate_owners ALTER owner_kind SET DEFAULT 0"), + Migration::add_table(20150804170128, + "teams", + " id SERIAL PRIMARY KEY, - login VARCHAR NOT NULL UNIQUE, - github_id INTEGER NOT NULL UNIQUE, + \ + login VARCHAR NOT NULL UNIQUE, + github_id \ + INTEGER NOT NULL UNIQUE, name VARCHAR, - avatar VARCHAR + \ + avatar VARCHAR "), - Migration::run(20150804170129, - "ALTER TABLE crate_owners RENAME user_id TO owner_id", - "ALTER TABLE crate_owners RENAME owner_id TO user_id", - ), - undo_foreign_key(20150804170130, "crate_owners", "user_id", - "owner_id", "users (id)"), - Migration::new(20150818112907, |tx| { + Migration::run(20150804170129, + "ALTER TABLE crate_owners RENAME user_id TO owner_id", + "ALTER TABLE crate_owners RENAME owner_id TO user_id"), + undo_foreign_key(20150804170130, + "crate_owners", + "user_id", + "owner_id", + "users (id)"), + Migration::new(20150818112907, + |tx| { try!(tx.execute("ALTER TABLE crate_owners DROP CONSTRAINT \ - crate_owners_unique_user_per_crate", &[])); + crate_owners_unique_user_per_crate", + &[])); try!(tx.execute("ALTER TABLE crate_owners ADD CONSTRAINT \ crate_owners_unique_owner_per_crate \ - UNIQUE (owner_id, crate_id, owner_kind)", &[])); + UNIQUE (owner_id, crate_id, owner_kind)", + &[])); Ok(()) - }, |tx| { + }, + |tx| { try!(tx.execute("ALTER TABLE crate_owners DROP CONSTRAINT \ - crate_owners_unique_owner_per_crate", &[])); + crate_owners_unique_owner_per_crate", + &[])); try!(tx.execute("ALTER TABLE crate_owners ADD CONSTRAINT \ crate_owners_unique_user_per_crate \ - UNIQUE (owner_id, crate_id)", &[])); + UNIQUE (owner_id, crate_id)", + &[])); Ok(()) }), - Migration::add_column(20151118135514, "crates", "max_upload_size", - "INTEGER"), - Migration::new(20151126095136, |tx| { + Migration::add_column(20151118135514, "crates", "max_upload_size", "INTEGER"), + Migration::new(20151126095136, + |tx| { try!(tx.batch_execute(" ALTER TABLE version_downloads ALTER downloads SET DEFAULT 1; ALTER TABLE version_downloads ALTER counted SET DEFAULT 0; @@ -539,7 +689,8 @@ fn migrations() -> Vec { ")); Ok(()) - }, |tx| { + }, + |tx| { try!(tx.batch_execute(" ALTER TABLE version_downloads ALTER downloads DROP DEFAULT; ALTER TABLE version_downloads ALTER counted DROP DEFAULT; @@ -573,7 +724,8 @@ fn migrations() -> Vec { ")); Ok(()) }), - Migration::new(20151211122515, |tx| { + Migration::new(20151211122515, + |tx| { try!(tx.batch_execute(" CREATE FUNCTION set_updated_at_ignore_downloads() RETURNS trigger AS $$ BEGIN @@ -596,7 +748,8 @@ fn migrations() -> Vec { FOR EACH ROW EXECUTE PROCEDURE set_updated_at_ignore_downloads(); ")); Ok(()) - }, |tx| { + }, + |tx| { try!(tx.batch_execute(" DROP TRIGGER trigger_crates_set_updated_at ON crates; DROP TRIGGER trigger_versions_set_updated_at ON versions; @@ -611,7 +764,8 @@ fn migrations() -> Vec { ")); Ok(()) }), - Migration::new(20160219125609, |tx| { + Migration::new(20160219125609, + |tx| { tx.batch_execute(" ALTER TABLE crates DROP COLUMN keywords; CREATE OR REPLACE FUNCTION trigger_crates_name_search() RETURNS trigger AS $$ @@ -651,7 +805,8 @@ fn migrations() -> Vec { FOR EACH ROW EXECUTE PROCEDURE touch_crate(); ") - }, |tx| { + }, + |tx| { tx.batch_execute(" ALTER TABLE crates ADD COLUMN keywords VARCHAR; CREATE OR REPLACE FUNCTION trigger_crates_name_search() RETURNS trigger AS $$ @@ -680,7 +835,8 @@ fn migrations() -> Vec { DROP FUNCTION touch_crate(); ") }), - Migration::new(20160326123149, |tx| { + Migration::new(20160326123149, + |tx| { use postgres::error::{Error, SqlState}; for row in try!(tx.query("SELECT id FROM keywords ORDER BY id", &[])).iter() { @@ -688,7 +844,8 @@ fn migrations() -> Vec { let err = { let tx = try!(tx.transaction()); let res = tx.execute("UPDATE keywords SET keyword = LOWER(keyword) - WHERE id = $1", &[&kw_id]); + WHERE id = $1", + &[&kw_id]); match res { Ok(n) => { assert_eq!(n, 1); @@ -707,7 +864,10 @@ fn migrations() -> Vec { SELECT id FROM keywords WHERE keyword = LOWER(( SELECT keyword FROM keywords WHERE id = $1 )) - ", &[&kw_id])).get(0).get(0); + ", + &[&kw_id])) + .get(0) + .get(0); try!(tx.batch_execute(&format!(" UPDATE crates_keywords SET keyword_id = {} @@ -716,101 +876,96 @@ fn migrations() -> Vec { SELECT crates_cnt FROM keywords WHERE id = {} ) WHERE id = {}; DELETE FROM keywords WHERE id = {}; - ", target_id, kw_id, kw_id, target_id, kw_id))); - }, - e => return Err(e) + ", + target_id, + kw_id, + kw_id, + target_id, + kw_id))); + } + e => return Err(e), } } Ok(()) - }, |_tx| { - Ok(()) - }), - Migration::run(20160717173343, - "DROP INDEX index_crates_user_id", - "CREATE INDEX index_crates_user_id \ - ON crates (user_id)", - ), - undo_foreign_key(20160717174005, "crates", "user_id", - "user_id", "users (id)"), - Migration::run(20160717174656, - "ALTER TABLE crates DROP COLUMN user_id", - "ALTER TABLE crates ADD COLUMN user_id INTEGER NOT NULL", - ), - - Migration::add_column(20160811151953, "users", "gh_id", "INTEGER"), - index(20160811151954, "users", "gh_id"), - Migration::new(20160812094501, |tx| { - try!(tx.execute("ALTER TABLE users ALTER COLUMN gh_id \ - SET NOT NULL", &[])); - Ok(()) - }, |tx| { - try!(tx.execute("ALTER TABLE users ALTER COLUMN gh_id \ + }, + |_tx| Ok(())), + Migration::run(20160717173343, + "DROP INDEX index_crates_user_id", + "CREATE INDEX index_crates_user_id ON crates (user_id)"), + undo_foreign_key(20160717174005, "crates", "user_id", "user_id", "users (id)"), + Migration::run(20160717174656, + "ALTER TABLE crates DROP COLUMN user_id", + "ALTER TABLE crates ADD COLUMN user_id INTEGER NOT NULL"), + + Migration::add_column(20160811151953, "users", "gh_id", "INTEGER"), + index(20160811151954, "users", "gh_id"), + Migration::new(20160812094501, + |tx| { + try!(tx.execute("ALTER TABLE users ALTER COLUMN gh_id SET NOT NULL", + &[])); + Ok(()) + }, + |tx| { + try!(tx.execute("ALTER TABLE users ALTER COLUMN gh_id \ DROP NOT NULL", &[])); - Ok(()) - }), - Migration::new(20160812094502, |tx| { + Ok(()) + }), + Migration::new(20160812094502, + |tx| { // Enusre that gh_id is always unique (sure hope it is), but // only where the id is > 0. Historically we didn't track id, and we // had to fill it in at one point after-the-fact. User rows that // couldn't be resolved either have a github id of 0 or -1 so they // can't ever be logged into again. try!(tx.execute("CREATE UNIQUE INDEX users_gh_id \ - ON users (gh_id) WHERE gh_id > 0", &[])); - Ok(()) - }, |tx| { - try!(tx.execute("DROP INDEX users_gh_id", &[])); + ON users (gh_id) WHERE gh_id > 0", + &[])); Ok(()) - }), - Migration::add_table(20161115110541, "categories", " \ - id SERIAL PRIMARY KEY, \ - category VARCHAR NOT NULL UNIQUE, \ - slug VARCHAR NOT NULL UNIQUE, \ - description VARCHAR NOT NULL DEFAULT '', \ - crates_cnt INTEGER NOT NULL DEFAULT 0, \ - created_at TIMESTAMP NOT NULL DEFAULT current_timestamp"), - Migration::add_table(20161115111828, "crates_categories", " \ - crate_id INTEGER NOT NULL, \ - category_id INTEGER NOT NULL"), - foreign_key(20161115111836, "crates_categories", "crate_id", "crates (id)"), - Migration::run(20161115111846, " \ - ALTER TABLE crates_categories \ - ADD CONSTRAINT fk_crates_categories_category_id \ - FOREIGN KEY (category_id) REFERENCES categories (id) \ - ON DELETE CASCADE", " \ - ALTER TABLE crates_categories \ - DROP CONSTRAINT fk_crates_categories_category_id"), - index(20161115111853, "crates_categories", "crate_id"), - index(20161115111900, "crates_categories", "category_id"), - Migration::new(20161115111957, |tx| { - try!(tx.batch_execute(" \ - CREATE FUNCTION update_categories_crates_cnt() \ - RETURNS trigger AS $$ \ - BEGIN \ - IF (TG_OP = 'INSERT') THEN \ - UPDATE categories \ - SET crates_cnt = crates_cnt + 1 \ - WHERE id = NEW.category_id; \ - return NEW; \ - ELSIF (TG_OP = 'DELETE') THEN \ - UPDATE categories \ - SET crates_cnt = crates_cnt - 1 \ - WHERE id = OLD.category_id; \ - return OLD; \ - END IF; \ - END \ - $$ LANGUAGE plpgsql; \ - CREATE TRIGGER trigger_update_categories_crates_cnt \ - BEFORE INSERT OR DELETE \ - ON crates_categories \ - FOR EACH ROW EXECUTE PROCEDURE update_categories_crates_cnt(); \ - CREATE TRIGGER touch_crate_on_modify_categories \ - AFTER INSERT OR DELETE ON crates_categories \ - FOR EACH ROW \ - EXECUTE PROCEDURE touch_crate(); \ - ")); + }, + |tx| { + try!(tx.execute("DROP INDEX users_gh_id", &[])); + Ok(()) + }), + Migration::add_table(20161115110541, + "categories", + " id SERIAL PRIMARY KEY, category \ + VARCHAR NOT NULL UNIQUE, slug VARCHAR NOT NULL \ + UNIQUE, description VARCHAR NOT NULL DEFAULT '', \ + crates_cnt INTEGER NOT NULL DEFAULT 0, created_at \ + TIMESTAMP NOT NULL DEFAULT current_timestamp"), + Migration::add_table(20161115111828, + "crates_categories", + " crate_id INTEGER NOT NULL, category_id INTEGER \ + NOT NULL"), + foreign_key(20161115111836, + "crates_categories", + "crate_id", + "crates (id)"), + Migration::run(20161115111846, + " ALTER TABLE crates_categories ADD CONSTRAINT \ + fk_crates_categories_category_id FOREIGN KEY (category_id) \ + REFERENCES categories (id) ON DELETE CASCADE", + " ALTER TABLE crates_categories DROP CONSTRAINT \ + fk_crates_categories_category_id"), + index(20161115111853, "crates_categories", "crate_id"), + index(20161115111900, "crates_categories", "category_id"), + Migration::new(20161115111957, + |tx| { + try!(tx.batch_execute(" CREATE FUNCTION update_categories_crates_cnt() RETURNS trigger \ + AS $$ BEGIN IF (TG_OP = 'INSERT') THEN UPDATE categories SET \ + crates_cnt = crates_cnt + 1 WHERE id = NEW.category_id; return \ + NEW; ELSIF (TG_OP = 'DELETE') THEN UPDATE categories SET \ + crates_cnt = crates_cnt - 1 WHERE id = OLD.category_id; return \ + OLD; END IF; END $$ LANGUAGE plpgsql; CREATE TRIGGER \ + trigger_update_categories_crates_cnt BEFORE INSERT OR DELETE ON \ + crates_categories FOR EACH ROW EXECUTE PROCEDURE \ + update_categories_crates_cnt(); CREATE TRIGGER \ + touch_crate_on_modify_categories AFTER INSERT OR DELETE ON \ + crates_categories FOR EACH ROW EXECUTE PROCEDURE touch_crate(); ")); Ok(()) - }, |tx| { + }, + |tx| { try!(tx.batch_execute(" \ DROP TRIGGER trigger_update_categories_crates_cnt \ ON crates_categories; \ @@ -819,19 +974,21 @@ fn migrations() -> Vec { ON crates_categories;")); Ok(()) }), - Migration::add_table(20170102131034, "badges", " \ - crate_id INTEGER NOT NULL, \ - badge_type VARCHAR NOT NULL, \ - attributes JSONB NOT NULL"), - Migration::new(20170102145236, |tx| { - try!(tx.execute("CREATE UNIQUE INDEX badges_crate_type \ - ON badges (crate_id, badge_type)", &[])); - Ok(()) - }, |tx| { - try!(tx.execute("DROP INDEX badges_crate_type", &[])); - Ok(()) - }), - ]; + Migration::add_table(20170102131034, + "badges", + " crate_id INTEGER NOT NULL, badge_type VARCHAR \ + NOT NULL, attributes JSONB NOT NULL"), + Migration::new(20170102145236, + |tx| { + try!(tx.execute("CREATE UNIQUE INDEX badges_crate_type ON \ + badges (crate_id, badge_type)", + &[])); + Ok(()) + }, + |tx| { + try!(tx.execute("DROP INDEX badges_crate_type", &[])); + Ok(()) + })]; // NOTE: Generate a new id via `date +"%Y%m%d%H%M%S"` let mut seen = HashSet::new(); @@ -842,35 +999,44 @@ fn migrations() -> Vec { } return migrations; - fn foreign_key(id: i64, table: &str, column: &str, - references: &str) -> Migration { + fn foreign_key(id: i64, table: &str, column: &str, references: &str) -> Migration { let add = format!("ALTER TABLE {table} ADD CONSTRAINT fk_{table}_{col} FOREIGN KEY ({col}) REFERENCES {reference}", - table = table, col = column, reference = references); + table = table, + col = column, + reference = references); let rm = format!("ALTER TABLE {table} DROP CONSTRAINT fk_{table}_{col}", - table = table, col = column); + table = table, + col = column); Migration::run(id, &add, &rm) } - fn undo_foreign_key(id: i64, table: &str, + fn undo_foreign_key(id: i64, + table: &str, column: &str, real_column: &str, - references: &str) -> Migration { + references: &str) + -> Migration { let add = format!("ALTER TABLE {table} ADD CONSTRAINT fk_{table}_{col} FOREIGN KEY ({real_col}) REFERENCES {reference}", - table = table, col = column, reference = references, + table = table, + col = column, + reference = references, real_col = real_column); let rm = format!("ALTER TABLE {table} DROP CONSTRAINT fk_{table}_{col}", - table = table, col = column); + table = table, + col = column); Migration::run(id, &rm, &add) } fn index(id: i64, table: &str, column: &str) -> Migration { let add = format!("CREATE INDEX index_{table}_{column} ON {table} ({column})", - table = table, column = column); + table = table, + column = column); let rm = format!("DROP INDEX index_{table}_{column}", - table = table, column = column); + table = table, + column = column); Migration::run(id, &add, &rm) } } @@ -883,9 +1049,9 @@ fn fix_duplicate_crate_owners(tx: &postgres::transaction::Transaction) -> postgr GROUP BY user_id, crate_id HAVING COUNT(*) > 1")); let rows = try!(stmt.query(&[])); - rows.iter().map(|row| { - (row.get("user_id"), row.get("crate_id")) - }).collect() + rows.iter() + .map(|row| (row.get("user_id"), row.get("crate_id"))) + .collect() }; for &(user_id, crate_id) in v.iter() { let stmt = try!(tx.prepare("SELECT id FROM crate_owners diff --git a/src/bin/populate.rs b/src/bin/populate.rs index bbb44d20616..97a1013821b 100644 --- a/src/bin/populate.rs +++ b/src/bin/populate.rs @@ -27,9 +27,7 @@ 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(); diff --git a/src/bin/server.rs b/src/bin/server.rs index 1af0ca68c87..9962cf29d1d 100644 --- a/src/bin/server.rs +++ b/src/bin/server.rs @@ -30,8 +30,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(); @@ -69,7 +70,11 @@ fn main() { } else { env::var("PORT").ok().and_then(|s| s.parse().ok()).unwrap_or(8888) }; - let threads = if cargo_env == cargo_registry::Env::Development {1} else {50}; + let threads = if cargo_env == cargo_registry::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 bf6cf2da6bb..2b1cd1ea32c 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,16 @@ 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 + 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"); @@ -73,8 +81,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 - WHERE id $2", - &[&to.id, &id]).unwrap(); + WHERE \ + id $2", + &[&to.id, &id]) + .unwrap(); assert_eq!(n, 1); } diff --git a/src/bin/update-downloads.rs b/src/bin/update-downloads.rs index bbf8e87d071..c0a1ba84899 100644 --- a/src/bin/update-downloads.rs +++ b/src/bin/update-downloads.rs @@ -16,8 +16,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(); @@ -26,7 +25,7 @@ fn main() { if daemon { std::thread::sleep(Duration::new(sleep.unwrap(), 0)); } else { - break + break; } } } @@ -36,7 +35,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 = try!(conn.transaction()); + let tx; + tx = try!(conn.transaction()); { let stmt = try!(tx.prepare("SELECT * FROM version_downloads \ WHERE processed = FALSE AND id > $1 @@ -55,7 +55,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> { use time::Duration; // Anything older than 24 hours ago will be frozen and will not be queried @@ -68,10 +69,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(), + println!("updating {} versions (cutoff {})", + map.len(), time::at(cutoff).rfc822()); if map.len() == 0 { - return Ok(None) + return Ok(None); } let mut max = 0; @@ -81,7 +83,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,12 +93,13 @@ fn collect(tx: &postgres::transaction::Transaction, SET processed = $2, counted = counted + $3 WHERE id = $1", &[id, &(download.date < cutoff), &amt])); - println!("{}\n{}", time::at(download.date).rfc822(), + println!("{}\n{}", + time::at(download.date).rfc822(), time::at(cutoff).rfc822()); total += amt as i64; if amt == 0 { - continue + continue; } let crate_id = Version::find(tx, download.version_id).unwrap().crate_id; @@ -108,7 +111,8 @@ fn collect(tx: &postgres::transaction::Transaction, &[&amt, &download.version_id])); // Update the total number of crate downloads try!(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 = try!(tx.execute("UPDATE crate_downloads @@ -144,20 +148,33 @@ 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", "api_token").unwrap() + fn user(conn: &postgres::transaction::Transaction) -> User { + User::find_or_insert(conn, + 2, + "login", + None, + None, + None, + "access_token", + "api_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); } @@ -166,20 +183,33 @@ 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(); - tx.execute("INSERT INTO version_downloads \ - (version_id) + &HashMap::new(), + &[]) + .unwrap(); + tx.execute("INSERT INTO version_downloads (version_id) VALUES ($1)", - &[&version.id]).unwrap(); - tx.execute("INSERT INTO version_downloads \ - (version_id, processed) - VALUES ($1, true)", - &[&version.id]).unwrap(); + &[&version.id]) + .unwrap(); + tx.execute("INSERT INTO version_downloads (version_id, processed) + \ + VALUES ($1, true)", + &[&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); @@ -193,21 +223,41 @@ 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(); - 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(); + &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(); ::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); } @@ -216,22 +266,41 @@ 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) + tx.execute("INSERT INTO version_downloads (version_id, downloads, counted, date, \ + processed) VALUES ($1, 2, 2, $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); } @@ -240,26 +309,43 @@ 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(); + SET updated_at = current_date - \ + interval '2 hours'", + &[]) + .unwrap(); tx.execute("UPDATE crates - SET updated_at = current_date - interval '2 hours'", - &[]).unwrap(); - tx.execute("INSERT INTO version_downloads \ - (version_id, downloads, counted, date, processed) + SET updated_at = current_date - \ + interval '2 hours'", + &[]) + .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) + &[&version.id]) + .unwrap(); + tx.execute("INSERT INTO version_downloads (version_id) VALUES ($1)", - &[&version.id]).unwrap(); + &[&version.id]) + .unwrap(); let version_before = Version::find(&tx, version.id).unwrap(); let krate_before = Crate::find(&tx, krate.id).unwrap(); @@ -280,22 +366,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(); tx.execute("UPDATE versions - SET updated_at = current_date - interval '2 days'", - &[]).unwrap(); + SET updated_at = current_date - \ + interval '2 days'", + &[]) + .unwrap(); tx.execute("UPDATE crates - SET updated_at = current_date - interval '2 days'", - &[]).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(); + SET updated_at = current_date - \ + interval '2 days'", + &[]) + .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(); 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 58cb986b398..f244d732efa 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) => { @@ -48,29 +51,28 @@ fn optional_string_from_toml<'a>(toml: &'a toml::Table, key: &str) -> &'a 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!("category {} was not a TOML table", slug)) - })?; + let details = details.as_table() + .chain_error(|| internal(format!("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!("child categories of {} were not a table", slug)) - })?; + let categories = + categories.as_table() + .chain_error(|| { + internal(format!("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 +86,28 @@ 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.iter() { 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] - )?; + 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])?; } - let in_clause = categories.iter().map(|ref category| { - format!("LOWER('{}')", category.slug) - }).collect::>().join(","); + let in_clause = categories.iter() + .map(|ref category| format!("LOWER('{}')", category.slug)) + .collect::>() + .join(","); tx.execute(&format!("\ - DELETE FROM categories \ - WHERE slug NOT IN ({});", - in_clause), - &[] - )?; + 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 49920dfeb3c..fac379b6785 100644 --- a/src/category.rs +++ b/src/category.rs @@ -43,30 +43,28 @@ 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 = try!(conn.prepare("SELECT * FROM categories \ WHERE category = $1")); let rows = try!(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 = try!(conn.prepare("SELECT * FROM categories \ WHERE slug = LOWER($1)")); let rows = try!(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 { - id: _, crates_cnt, category, slug, description, created_at - } = self; + let Category { id: _, crates_cnt, category, slug, description, created_at } = self; EncodableCategory { id: slug.clone(), slug: slug.clone(), @@ -79,37 +77,36 @@ impl Category { pub fn update_crate(conn: &GenericConnection, krate: &Crate, - categories: &[String]) -> CargoResult> { + categories: &[String]) + -> CargoResult> { let old_categories = try!(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) { + 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(); + } + }) + .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(); - let to_add: Vec<_> = new_categories_ids - .difference(&old_categories_ids) - .cloned() - .collect(); + let to_rm: Vec<_> = old_categories_ids.difference(&new_categories_ids) + .cloned() + .collect(); + let to_add: Vec<_> = new_categories_ids.difference(&old_categories_ids) + .cloned() + .collect(); if !to_rm.is_empty() { try!(conn.execute("DELETE FROM crates_categories \ @@ -119,9 +116,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(", "); try!(conn.execute(&format!("INSERT INTO crates_categories \ (crate_id, category_id) VALUES {}", @@ -134,11 +131,8 @@ impl Category { pub fn count_toplevel(conn: &GenericConnection) -> CargoResult { let sql = format!("\ - SELECT COUNT(*) \ - FROM {} \ - WHERE category NOT LIKE '%::%'", - Model::table_name(None:: - )); + SELECT COUNT(*) FROM {} WHERE category NOT LIKE '%::%'", + Model::table_name(None::)); let stmt = try!(conn.prepare(&sql)); let rows = try!(stmt.query(&[])); Ok(rows.iter().next().unwrap().get("count")) @@ -147,7 +141,8 @@ impl Category { pub fn toplevel(conn: &GenericConnection, sort: &str, limit: i64, - offset: i64) -> CargoResult> { + offset: i64) + -> CargoResult> { let sort_sql = match sort { "crates" => "ORDER BY crates_cnt DESC", @@ -156,19 +151,13 @@ impl Category { // Collect all the top-level categories and sum up the crates_cnt of // the crates in all subcategories - let stmt = try!(conn.prepare(&format!( - "SELECT c.id, c.category, c.slug, c.description, c.created_at, \ - COALESCE (( \ - SELECT sum(c2.crates_cnt)::int \ - FROM categories as c2 \ - WHERE c2.slug = c.slug \ - OR c2.slug LIKE c.slug || '::%' \ - ), 0) as crates_cnt \ - FROM categories as c \ - WHERE c.category NOT LIKE '%::%' {} \ - LIMIT $1 OFFSET $2", - sort_sql - ))); + let stmt = try!(conn.prepare(&format!("SELECT c.id, c.category, c.slug, c.description, \ + c.created_at, COALESCE (( SELECT \ + sum(c2.crates_cnt)::int FROM categories as c2 WHERE \ + c2.slug = c.slug OR c2.slug LIKE c.slug || '::%' ), 0) \ + as crates_cnt FROM categories as c WHERE c.category \ + NOT LIKE '%::%' {} LIMIT $1 OFFSET $2", + sort_sql))); let categories: Vec<_> = try!(stmt.query(&[&limit, &offset])) .iter() @@ -178,19 +167,14 @@ impl Category { Ok(categories) } - pub fn subcategories(&self, conn: &GenericConnection) - -> CargoResult> { + pub fn subcategories(&self, conn: &GenericConnection) -> CargoResult> { let stmt = try!(conn.prepare("\ - SELECT c.id, c.category, c.slug, c.description, c.created_at, \ - COALESCE (( \ - SELECT sum(c2.crates_cnt)::int \ - FROM categories as c2 \ - WHERE c2.slug = c.slug \ - OR c2.slug LIKE c.slug || '::%' \ - ), 0) as crates_cnt \ - FROM categories as c \ - WHERE c.category ILIKE $1 || '::%' \ - AND c.category NOT ILIKE $1 || '::%::%'")); + SELECT c.id, c.category, c.slug, \ + c.description, c.created_at, COALESCE (( SELECT \ + sum(c2.crates_cnt)::int FROM categories as c2 WHERE \ + c2.slug = c.slug OR c2.slug LIKE c.slug || '::%' ), 0) as \ + crates_cnt FROM categories as c WHERE c.category ILIKE $1 \ + || '::%' AND c.category NOT ILIKE $1 || '::%::%'")); let rows = try!(stmt.query(&[&self.category])); Ok(rows.iter().map(|r| Model::from_row(&r)).collect()) @@ -208,7 +192,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. @@ -225,9 +211,14 @@ pub fn index(req: &mut Request) -> CargoResult { let total = try!(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, @@ -240,9 +231,10 @@ pub fn show(req: &mut Request) -> CargoResult { let slug = &req.params()["category_id"]; let conn = try!(req.tx()); let cat = try!(Category::find_by_slug(&*conn, &slug)); - let subcats = try!(cat.subcategories(&*conn)).into_iter().map(|s| { - s.encodable() - }).collect(); + let subcats = try!(cat.subcategories(&*conn)) + .into_iter() + .map(|s| s.encodable()) + .collect(); let cat = cat.encodable(); let cat_with_subcats = EncodableCategoryWithSubcategories { id: cat.id, @@ -255,7 +247,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 })) } @@ -267,14 +261,24 @@ pub fn slugs(req: &mut Request) -> CargoResult { let rows = try!(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 })) } diff --git a/src/config.rs b/src/config.rs index 76483c58321..32653145db0 100644 --- a/src/config.rs +++ b/src/config.rs @@ -21,6 +21,10 @@ impl Config { pub fn api_protocol(&self) -> &'static str { // When testing we route all API traffic over HTTP so we can // sniff/record it, but everywhere else we use https - if self.env == ::Env::Test {"http"} else {"https"} + if self.env == ::Env::Test { + "http" + } else { + "https" + } } } diff --git a/src/db.rs b/src/db.rs index a50dfaf2272..840eb9904a9 100644 --- a/src/db.rs +++ b/src/db.rs @@ -71,7 +71,7 @@ pub fn tls_handshake() -> Box { let mut builder = SslConnectorBuilder::new(SslMethod::tls()).unwrap(); builder.builder_mut() - .set_verify(SSL_VERIFY_NONE); + .set_verify(SSL_VERIFY_NONE); Box::new(MyHandshake(builder.build())) } @@ -129,11 +129,14 @@ impl Transaction { } } - pub fn conn(&self) -> CargoResult<&r2d2::PooledConnection> { + pub fn conn + (&self) + -> CargoResult<&r2d2::PooledConnection> { if !self.slot.filled() { - let conn = try!(self.app.database.get().map_err(|e| { - internal(format!("failed to get a database connection: {}", e)) - })); + let conn = try!(self.app + .database + .get() + .map_err(|e| internal(format!("failed to get a database connection: {}", e)))); self.slot.fill(Box::new(conn)); } Ok(&**self.slot.borrow().unwrap()) @@ -169,25 +172,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(); } - try!(transaction.finish().map_err(|e| { - Box::new(e) as Box - })); + try!(transaction.finish().map_err(|e| Box::new(e) as Box)); } - return res + return res; } } @@ -195,7 +199,9 @@ pub trait RequestTransaction { /// Return the lazily initialized postgres connection for this request. /// /// The connection will live for the lifetime of the request. - fn db_conn(&self) -> CargoResult<&r2d2::PooledConnection>; + fn db_conn + (&self) + -> CargoResult<&r2d2::PooledConnection>; /// Return the lazily initialized postgres transaction for this request. /// @@ -210,26 +216,32 @@ pub trait RequestTransaction { } impl<'a> RequestTransaction for Request + 'a { - fn db_conn(&self) -> CargoResult<&r2d2::PooledConnection> { - self.extensions().find::() + fn db_conn + (&self) + -> CargoResult<&r2d2::PooledConnection> { + self.extensions() + .find::() .expect("Transaction not present in request") .conn() } 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 78db2f8afd5..4654494850a 100644 --- a/src/dependency.rs +++ b/src/dependency.rs @@ -4,7 +4,7 @@ use semver; use Model; use git; -use util::{CargoResult}; +use util::CargoResult; pub struct Dependency { pub id: i32, @@ -39,15 +39,18 @@ pub enum Kind { Normal, Build, Dev, - - // if you add a kind here, be sure to update `from_row` below. } impl Dependency { - 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 features = features.join(","); @@ -56,16 +59,27 @@ impl Dependency { default_features, features, target, kind) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *")); - let rows = try!(stmt.query(&[&version_id, &crate_id, &req, - &optional, &default_features, - &features, target, &(kind as i32)])); + let rows = try!(stmt.query(&[&version_id, + &crate_id, + &req, + &optional, + &default_features, + &features, + target, + &(kind as i32)])); Ok(Model::from_row(&rows.iter().next().unwrap())) } pub fn git_encode(&self, crate_name: &str) -> git::Dependency { - let Dependency { id: _, version_id: _, crate_id: _, ref req, - optional, default_features, ref features, - ref target, kind } = *self; + let Dependency { id: _, + version_id: _, + crate_id: _, + ref req, + optional, + default_features, + ref features, + ref target, + kind } = *self; git::Dependency { name: crate_name.to_string(), req: req.to_string(), @@ -115,18 +129,21 @@ impl Model for Dependency { req: semver::VersionReq::parse(&req).unwrap(), optional: row.get("optional"), default_features: row.get("default_features"), - features: features.split(',').filter(|s| !s.is_empty()) - .map(|s| s.to_string()) - .collect(), + features: features.split(',') + .filter(|s| !s.is_empty()) + .map(|s| s.to_string()) + .collect(), target: row.get("target"), kind: match kind.unwrap_or(0) { 0 => Kind::Normal, 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" + } } diff --git a/src/dist.rs b/src/dist.rs index 6678fed4d5a..a03a557c526 100644 --- a/src/dist.rs +++ b/src/dist.rs @@ -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,9 +37,10 @@ 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, diff --git a/src/download.rs b/src/download.rs index c995fb90cf4..f49a5f4c7d8 100644 --- a/src/download.rs +++ b/src/download.rs @@ -21,8 +21,7 @@ pub struct EncodableVersionDownload { impl VersionDownload { pub fn encodable(self) -> EncodableVersionDownload { - let VersionDownload { id, version_id, downloads, counted: _, - date } = self; + let VersionDownload { id, version_id, downloads, counted: _, date } = self; EncodableVersionDownload { id: id, version: version_id, @@ -43,7 +42,9 @@ impl Model for VersionDownload { } } - fn table_name(_: Option) -> &'static str { "version_downloads" } + fn table_name(_: Option) -> &'static str { + "version_downloads" + } } pub struct CrateDownload { @@ -63,5 +64,7 @@ impl Model for CrateDownload { } } - fn table_name(_: Option) -> &'static str { "crate_downloads" } + fn table_name(_: Option) -> &'static str { + "crate_downloads" + } } diff --git a/src/git.rs b/src/git.rs index 6d31c5c9c0c..c2506090dd4 100644 --- a/src/git.rs +++ b/src/git.rs @@ -39,9 +39,11 @@ fn index_file(base: &Path, name: &str) -> PathBuf { 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) + } } } @@ -64,13 +66,11 @@ pub fn add_crate(app: &App, krate: &Crate) -> CargoResult<()> { try!(f.write_all(new.as_bytes())); try!(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 = &*repo; let repo_path = repo.workdir().unwrap(); @@ -79,25 +79,26 @@ pub fn yank(app: &App, krate: &str, version: &semver::Version, commit_and_push(repo, || { let mut prev = String::new(); try!(File::open(&dst).and_then(|mut f| f.read_to_string(&mut prev))); - let new = prev.lines().map(|line| { - let mut git_crate = try!(json::decode::(line).map_err(|_| { - internal(format!("couldn't decode: `{}`", line)) - })); - if git_crate.name != krate || - git_crate.vers.to_string() != version.to_string() { - return Ok(line.to_string()) - } - git_crate.yanked = Some(yanked); - Ok(json::encode(&git_crate).unwrap()) - }).collect::>>(); + let new = prev.lines() + .map(|line| { + let mut git_crate = try!(json::decode::(line) + .map_err(|_| internal(format!("couldn't decode: `{}`", line)))); + if git_crate.name != krate || git_crate.vers.to_string() != version.to_string() { + return Ok(line.to_string()); + } + git_crate.yanked = Some(yanked); + Ok(json::encode(&git_crate).unwrap()) + }) + .collect::>>(); let new = try!(new).join("\n"); let mut f = try!(File::create(&dst)); try!(f.write_all(new.as_bytes())); try!(f.write_all(b"\n")); Ok((format!("{} crate `{}#{}`", - if yanked {"Yanking"} else {"Unyanking"}, - krate, version), + if yanked { "Yanking" } else { "Unyanking" }, + krate, + version), dst.clone())) }) } @@ -117,8 +118,9 @@ fn commit_and_push(repo: &git2::Repository, mut f: F) -> CargoResult<()> // git add $file let mut index = try!(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::(); try!(index.add_path(&dst)); try!(index.write()); let tree_id = try!(index.write_tree()); @@ -153,7 +155,8 @@ fn commit_and_push(repo: &git2::Repository, mut f: F) -> CargoResult<()> let mut callbacks = git2::RemoteCallbacks::new(); callbacks.credentials(credentials); - try!(origin.update_tips(Some(&mut callbacks), true, + try!(origin.update_tips(Some(&mut callbacks), + true, git2::AutotagOption::Unspecified, None)); @@ -167,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 a3e9ad022e7..e6debdad330 100644 --- a/src/http.rs +++ b/src/http.rs @@ -10,8 +10,7 @@ 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); @@ -29,17 +28,17 @@ pub fn github(app: &App, url: &str, auth: &Token) { let mut transfer = handle.transfer(); transfer.write_function(|buf| { - data.extend_from_slice(buf); - Ok(buf.len()) - }).unwrap(); + data.extend_from_slice(buf); + Ok(buf.len()) + }) + .unwrap(); try!(transfer.perform()); } Ok((handle, data)) } /// Checks for normal responses -pub fn parse_github_response(mut resp: Easy, data: Vec) - -> CargoResult { +pub fn parse_github_response(mut resp: Easy, data: Vec) -> CargoResult { match resp.response_code().unwrap() { 200 => {} // Ok! 403 => { @@ -54,17 +53,17 @@ pub fn parse_github_response(mut resp: Easy, data: Vec) n => { let resp = String::from_utf8_lossy(&data); return Err(internal(format!("didn't get a 200 result from \ - github, got {} with: {}", n, resp))); + github, got {} with: {}", + n, + resp))); } } - let json = try!(str::from_utf8(&data).ok().chain_error(||{ - internal("github didn't send a utf8-response") - })); + let json = try!(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 f82615c6fb2..f6fcb1c3b0d 100644 --- a/src/keyword.rs +++ b/src/keyword.rs @@ -29,42 +29,43 @@ pub struct EncodableKeyword { } impl Keyword { - pub fn find_by_keyword(conn: &GenericConnection, name: &str) - -> CargoResult> { + pub fn find_by_keyword(conn: &GenericConnection, name: &str) -> CargoResult> { let stmt = try!(conn.prepare("SELECT * FROM keywords \ WHERE keyword = LOWER($1)")); let rows = try!(stmt.query(&[&name])); Ok(rows.iter().next().map(|r| Model::from_row(&r))) } - pub fn find_or_insert(conn: &GenericConnection, name: &str) - -> CargoResult { + pub fn find_or_insert(conn: &GenericConnection, name: &str) -> CargoResult { // TODO: racy (the select then insert is not atomic) let stmt = try!(conn.prepare("SELECT * FROM keywords WHERE keyword = LOWER($1)")); for row in try!(stmt.query(&[&name])).iter() { - return Ok(Model::from_row(&row)) + return Ok(Model::from_row(&row)); } let stmt = try!(conn.prepare("INSERT INTO keywords (keyword) VALUES (LOWER($1)) RETURNING *")); let rows = try!(stmt.query(&[&name])); - Ok(Model::from_row(&try!(rows.iter().next().chain_error(|| { - internal("no version returned") - })))) + Ok(Model::from_row(&try!(rows.iter() + .next() + .chain_error(|| internal("no version returned"))))) } - pub fn all(conn: &GenericConnection, sort: &str, limit: i64, offset: i64) + pub fn all(conn: &GenericConnection, + sort: &str, + limit: i64, + offset: i64) -> CargoResult> { let sort_sql = match sort { - "crates" => "ORDER BY crates_cnt DESC", - _ => "ORDER BY keyword ASC", + "crates" => "ORDER BY crates_cnt DESC", + _ => "ORDER BY keyword ASC", }; let stmt = try!(conn.prepare(&format!("SELECT * FROM keywords {} LIMIT $1 OFFSET $2", - sort_sql))); + sort_sql))); let keywords: Vec<_> = try!(stmt.query(&[&limit, &offset])) .iter() @@ -75,10 +76,12 @@ impl Keyword { } pub fn valid_name(name: &str) -> bool { - if name.len() == 0 { return false } + if name.len() == 0 { + 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 { @@ -93,22 +96,27 @@ impl Keyword { pub fn update_crate(conn: &GenericConnection, krate: &Crate, - keywords: &[String]) -> CargoResult<()> { + keywords: &[String]) + -> CargoResult<()> { let old_kws = try!(krate.keywords(conn)); - let old_kws = old_kws.iter().map(|kw| { - (&kw.keyword[..], kw) - }).collect::>(); - let new_kws = try!(keywords.iter().map(|k| { - let kw = try!(Keyword::find_or_insert(conn, &k)); - Ok((&k[..], kw)) - }).collect::>>()); - - let to_rm = old_kws.iter().filter(|&(kw, _)| { - !new_kws.contains_key(kw) - }).map(|(_, v)| v.id).collect::>(); - let to_add = new_kws.iter().filter(|&(kw, _)| { - !old_kws.contains_key(kw) - }).map(|(_, v)| v.id).collect::>(); + let old_kws = old_kws.iter() + .map(|kw| (&kw.keyword[..], kw)) + .collect::>(); + let new_kws = try!(keywords.iter() + .map(|k| { + let kw = try!(Keyword::find_or_insert(conn, &k)); + Ok((&k[..], kw)) + }) + .collect::>>()); + + let to_rm = old_kws.iter() + .filter(|&(kw, _)| !new_kws.contains_key(kw)) + .map(|(_, v)| v.id) + .collect::>(); + let to_add = new_kws.iter() + .filter(|&(kw, _)| !old_kws.contains_key(kw)) + .map(|(_, v)| v.id) + .collect::>(); if to_rm.len() > 0 { try!(conn.execute("DELETE FROM crates_keywords @@ -118,11 +126,14 @@ impl Keyword { } if to_add.len() > 0 { - let insert = to_add.iter().map(|id| { - let crate_id: i32 = krate.id; - let id: i32 = *id; - format!("({}, {})", crate_id, id) - }).collect::>().join(", "); + let insert = to_add.iter() + .map(|id| { + let crate_id: i32 = krate.id; + let id: i32 = *id; + format!("({}, {})", crate_id, id) + }) + .collect::>() + .join(", "); try!(conn.execute(&format!("INSERT INTO crates_keywords (crate_id, keyword_id) VALUES {}", insert), @@ -142,7 +153,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. @@ -159,9 +172,14 @@ pub fn index(req: &mut Request) -> CargoResult { let total = try!(Keyword::count(conn)); #[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: keywords, @@ -177,6 +195,8 @@ pub fn show(req: &mut Request) -> CargoResult { let kw = try!(kw.chain_error(|| NotFound)); #[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 19717660979..8e4a0b5e406 100644 --- a/src/krate.rs +++ b/src/krate.rs @@ -83,8 +83,7 @@ pub struct CrateLinks { } impl Crate { - pub fn find_by_name(conn: &GenericConnection, - name: &str) -> CargoResult { + pub fn find_by_name(conn: &GenericConnection, name: &str) -> CargoResult { let stmt = try!(conn.prepare("SELECT * FROM crates \ WHERE canon_crate_name(name) = canon_crate_name($1) LIMIT 1")); @@ -143,9 +142,12 @@ impl Crate { WHERE canon_crate_name(name) = canon_crate_name($7) RETURNING *")); - let rows = try!(stmt.query(&[&documentation, &homepage, - &description, &readme, - &license, &repository, + let rows = try!(stmt.query(&[&documentation, + &homepage, + &description, + &readme, + &license, + &repository, &name])); match rows.iter().next() { Some(row) => return Ok(Model::from_row(&row)), @@ -156,7 +158,7 @@ impl Crate { const RESERVED: &'static str = include_str!("reserved_crates.txt"); if RESERVED.lines().any(|krate| name == krate) { - return Err(human("cannot upload a crate with a reserved name")) + return Err(human("cannot upload a crate with a reserved name")); } let stmt = try!(conn.prepare("INSERT INTO crates @@ -165,12 +167,17 @@ impl Crate { repository, license, max_upload_size) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *")); - let rows = try!(stmt.query(&[&name, &description, &homepage, - &documentation, &readme, - &repository, &license, &max_upload_size])); - let ret: Crate = Model::from_row(&try!(rows.iter().next().chain_error(|| { - internal("no crate returned") - }))); + let rows = try!(stmt.query(&[&name, + &description, + &homepage, + &documentation, + &readme, + &repository, + &license, + &max_upload_size])); + let ret: Crate = Model::from_row(&try!(rows.iter() + .next() + .chain_error(|| internal("no crate returned")))); try!(conn.execute("INSERT INTO crate_owners (crate_id, owner_id, created_by, owner_kind) @@ -181,40 +188,45 @@ 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 = try!(Url::parse(url).map_err(|_| { - human(format!("`{}` is not a valid url: `{}`", field, url)) - })); + let url = try!(Url::parse(url) + .map_err(|_| human(format!("`{}` is not a valid url: `{}`", field, url)))); match &url.scheme()[..] { "http" | "https" => {} - s => return Err(human(format!("`{}` has an invalid url \ - scheme: `{}`", field, s))) + s => return Err(human(format!("`{}` has an invalid url scheme: `{}`", field, s))), } if url.cannot_be_a_base() { return Err(human(format!("`{}` 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!("{}; see http://opensource.org/licenses \ - for options, and http://spdx.org/licenses/ \ - for their identifiers", e))) + license.iter() + .flat_map(|s| s.split("/")) + .map(license_exprs::validate_license_expr) + .collect::, _>>() + .map(|_| ()) + .map_err(|e| { + human(format!("{}; see http://opensource.org/licenses for options, and \ + http://spdx.org/licenses/ for their identifiers", + e)) + }) } } pub fn valid_name(name: &str) -> bool { - if name.len() == 0 { return false } + if name.len() == 0 { + 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 { @@ -231,8 +243,7 @@ impl Crate { parts.next().is_none() } - pub fn minimal_encodable(self, - badges: Option>) -> EncodableCrate { + pub fn minimal_encodable(self, badges: Option>) -> EncodableCrate { self.encodable(None, None, None, badges) } @@ -242,20 +253,26 @@ impl Crate { categories: Option<&[Category]>, badges: Option>) -> EncodableCrate { - let Crate { - name, created_at, updated_at, downloads, max_version, description, - homepage, documentation, license, repository, - readme: _, id: _, max_upload_size: _, - } = self; + let Crate { name, + created_at, + updated_at, + downloads, + max_version, + description, + homepage, + documentation, + license, + repository, + readme: _, + id: _, + max_upload_size: _ } = self; let versions_link = match versions { Some(..) => None, None => Some(format!("/api/v1/crates/{}/versions", name)), }; 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.iter().map(|b| b.clone().encodable()).collect() - }); + let badges = badges.map(|bs| bs.iter().map(|b| b.clone().encodable()).collect()); EncodableCrate { id: name.clone(), name: name.clone(), @@ -276,7 +293,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), }, } } @@ -285,9 +302,9 @@ impl Crate { let stmt = try!(conn.prepare("SELECT * FROM versions \ WHERE crate_id = $1")); let rows = try!(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) } @@ -315,21 +332,28 @@ impl Crate { Ok(owners) } - pub fn owner_add(&self, app: &App, conn: &GenericConnection, req_user: &User, - login: &str) -> CargoResult<()> { + pub fn owner_add(&self, + app: &App, + conn: &GenericConnection, + 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 try!(team.contains_user(app, req_user)) { - Owner::Team(team) - } else { - return Err(human(format!("only members of {} can add it as \ - an owner", login))); - }, - Err(err) => if login.contains(":") { - Owner::Team(try!(Team::create(app, conn, login, req_user))) - } else { - return Err(err); - }, + Ok(owner @ Owner::User(_)) => owner, + Ok(Owner::Team(team)) => { + if try!(team.contains_user(app, req_user)) { + Owner::Team(team) + } else { + return Err(human(format!("only members of {} can add it as an owner", login))); + } + } + Err(err) => { + if login.contains(":") { + Owner::Team(try!(Team::create(app, conn, login, req_user))) + } else { + return Err(err); + } + } }; // First try to un-delete if they've been soft deleted previously, then @@ -344,8 +368,7 @@ impl Crate { try!(conn.execute("INSERT INTO crate_owners (crate_id, owner_id, created_by, owner_kind) VALUES ($1, $2, $3, $4)", - &[&self.id, &owner.id(), &req_user.id, - &owner.kind()])); + &[&self.id, &owner.id(), &req_user.id, &owner.kind()])); } Ok(()) @@ -354,10 +377,10 @@ impl Crate { pub fn owner_remove(&self, conn: &GenericConnection, _req_user: &User, - login: &str) -> CargoResult<()> { - let owner = try!(Owner::find_by_login(conn, login).map_err(|_| { - human(format!("could not find owner with login `{}`", login)) - })); + login: &str) + -> CargoResult<()> { + let owner = try!(Owner::find_by_login(conn, login) + .map_err(|_| human(format!("could not find owner with login `{}`", login)))); try!(conn.execute("UPDATE crate_owners SET deleted = TRUE WHERE crate_id = $1 AND owner_id = $2 @@ -377,10 +400,7 @@ impl Crate { authors: &[String]) -> CargoResult { match try!(Version::find_by_num(conn, self.id, ver)) { - Some(..) => { - return Err(human(format!("crate version `{}` is already uploaded", - ver))) - } + Some(..) => return Err(human(format!("crate version `{}` is already uploaded", ver))), None => {} } let zero = semver::Version::parse("0.0.0").unwrap(); @@ -404,11 +424,10 @@ impl Crate { } pub fn categories(&self, conn: &GenericConnection) -> CargoResult> { - let stmt = try!(conn.prepare("SELECT categories.* FROM categories \ - LEFT JOIN crates_categories \ - ON categories.id = \ - crates_categories.category_id \ - WHERE crates_categories.crate_id = $1")); + let stmt = + try!(conn.prepare("SELECT categories.* FROM categories LEFT JOIN crates_categories ON \ + categories.id = crates_categories.category_id WHERE \ + crates_categories.crate_id = $1")); let rows = try!(stmt.query(&[&self.id])); Ok(rows.iter().map(|r| Model::from_row(&r)).collect()) } @@ -477,7 +496,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. @@ -499,94 +520,137 @@ pub fn index(req: &mut Request) -> CargoResult { let mut id = -1; let (mut needs_id, mut needs_pattern) = (false, false); let mut args = vec![&limit as &ToSql, &offset]; - let (q, cnt) = query.get("q").map(|query| { - args.insert(0, query); - let rank_sort_sql = match sort { - "downloads" => format!("{}, rank DESC", sort_sql), - _ => format!("rank DESC, {}", sort_sql), - }; - (format!("SELECT crates.* FROM crates, - plainto_tsquery($1) q, - ts_rank_cd(textsearchable_index_col, q) rank - WHERE q @@ textsearchable_index_col + let (q, cnt) = query.get("q") + .map(|query| { + args.insert(0, query); + let rank_sort_sql = match sort { + "downloads" => format!("{}, rank DESC", sort_sql), + _ => format!("rank DESC, {}", sort_sql), + }; + (format!("SELECT crates.* FROM crates, + \ + plainto_tsquery($1) q, + \ + ts_rank_cd(textsearchable_index_col, q) rank + WHERE q @@ \ + textsearchable_index_col ORDER BY name = $1 DESC, {} - LIMIT $2 OFFSET $3", rank_sort_sql), - "SELECT COUNT(crates.*) FROM crates, - plainto_tsquery($1) q - WHERE q @@ textsearchable_index_col".to_string()) - }).or_else(|| { - query.get("letter").map(|letter| { - pattern = format!("{}%", letter.chars().next().unwrap() - .to_lowercase().collect::()); - needs_pattern = true; - (format!("SELECT * FROM crates WHERE canon_crate_name(name) \ - LIKE $1 ORDER BY {} LIMIT $2 OFFSET $3", sort_sql), - "SELECT COUNT(*) FROM crates WHERE canon_crate_name(name) \ - LIKE $1".to_string()) + \ + LIMIT $2 OFFSET $3", + rank_sort_sql), + "SELECT COUNT(crates.*) FROM crates, + \ + plainto_tsquery($1) q + WHERE q @@ textsearchable_index_col" + .to_string()) }) - }).or_else(|| { - query.get("keyword").map(|kw| { - args.insert(0, kw); - let base = "FROM crates + .or_else(|| { + query.get("letter").map(|letter| { + pattern = format!("{}%", + letter.chars() + .next() + .unwrap() + .to_lowercase() + .collect::()); + needs_pattern = true; + (format!("SELECT * FROM crates WHERE canon_crate_name(name) LIKE $1 ORDER BY {} \ + LIMIT $2 OFFSET $3", + sort_sql), + "SELECT COUNT(*) FROM crates WHERE canon_crate_name(name) LIKE $1".to_string()) + }) + }) + .or_else(|| { + query.get("keyword").map(|kw| { + args.insert(0, kw); + let base = "FROM crates INNER JOIN crates_keywords - ON crates.id = crates_keywords.crate_id - INNER JOIN keywords - ON crates_keywords.keyword_id = keywords.id - WHERE lower(keywords.keyword) = lower($1)"; - (format!("SELECT crates.* {} ORDER BY {} LIMIT $2 OFFSET $3", base, sort_sql), - format!("SELECT COUNT(crates.*) {}", base)) + \ + ON crates.id = crates_keywords.crate_id + INNER \ + JOIN keywords + ON \ + crates_keywords.keyword_id = keywords.id + \ + WHERE lower(keywords.keyword) = lower($1)"; + (format!("SELECT crates.* {} ORDER BY {} LIMIT $2 OFFSET $3", + base, + sort_sql), + format!("SELECT COUNT(crates.*) {}", base)) + }) }) - }).or_else(|| { - query.get("category").map(|cat| { - args.insert(0, cat); - let base = "FROM crates + .or_else(|| { + query.get("category").map(|cat| { + args.insert(0, cat); + let base = "FROM crates INNER JOIN crates_categories - ON crates.id = crates_categories.crate_id - INNER JOIN categories - ON crates_categories.category_id = - categories.id + \ + ON crates.id = crates_categories.crate_id + \ + INNER JOIN categories + ON \ + crates_categories.category_id = + \ + categories.id WHERE categories.slug = $1 OR - categories.slug LIKE $1 || '::%'"; - (format!("SELECT DISTINCT crates.* {} ORDER BY {} LIMIT $2 OFFSET $3", base, sort_sql), - format!("SELECT COUNT(DISTINCT crates.*) {}", base)) + \ + categories.slug LIKE $1 || '::%'"; + (format!("SELECT DISTINCT crates.* {} ORDER BY {} LIMIT $2 OFFSET $3", + base, + sort_sql), + format!("SELECT COUNT(DISTINCT crates.*) {}", base)) + }) }) - }).or_else(|| { - query.get("user_id").and_then(|s| s.parse::().ok()).map(|user_id| { - id = user_id; - needs_id = true; - (format!("SELECT crates.* FROM crates - INNER JOIN crate_owners - ON crate_owners.crate_id = crates.id + .or_else(|| { + query.get("user_id").and_then(|s| s.parse::().ok()).map(|user_id| { + id = user_id; + needs_id = true; + (format!("SELECT crates.* FROM crates + INNER JOIN \ + crate_owners + ON crate_owners.crate_id = \ + crates.id WHERE crate_owners.owner_id = $1 - AND crate_owners.owner_kind = {} + \ + AND crate_owners.owner_kind = {} ORDER BY {} - LIMIT $2 OFFSET $3", - OwnerKind::User as i32, sort_sql), - format!("SELECT COUNT(crates.*) FROM crates - INNER JOIN crate_owners + \ + LIMIT $2 OFFSET $3", + OwnerKind::User as i32, + sort_sql), + format!("SELECT COUNT(crates.*) FROM crates + INNER JOIN \ + crate_owners ON crate_owners.crate_id = crates.id - WHERE crate_owners.owner_id = $1 \ - AND crate_owners.owner_kind = {}", - OwnerKind::User as i32)) + \ + WHERE crate_owners.owner_id = $1 AND crate_owners.owner_kind = {}", + OwnerKind::User as i32)) + }) }) - }).or_else(|| { - query.get("following").map(|_| { - needs_id = true; - (format!("SELECT crates.* FROM crates + .or_else(|| { + query.get("following").map(|_| { + needs_id = true; + (format!("SELECT crates.* FROM crates INNER JOIN follows - ON follows.crate_id = crates.id AND - follows.user_id = $1 ORDER BY - {} LIMIT $2 OFFSET $3", sort_sql), - "SELECT COUNT(crates.*) FROM crates + \ + ON follows.crate_id = crates.id AND + \ + follows.user_id = $1 ORDER BY + {} LIMIT $2 OFFSET \ + $3", + sort_sql), + "SELECT COUNT(crates.*) FROM crates INNER JOIN follows - ON follows.crate_id = crates.id AND - follows.user_id = $1".to_string()) + \ + ON follows.crate_id = crates.id AND + follows.user_id = $1" + .to_string()) + }) }) - }).unwrap_or_else(|| { - (format!("SELECT * FROM crates ORDER BY {} LIMIT $1 OFFSET $2", - sort_sql), - "SELECT COUNT(*) FROM crates".to_string()) - }); + .unwrap_or_else(|| { + (format!("SELECT * FROM crates ORDER BY {} LIMIT $1 OFFSET $2", + sort_sql), + "SELECT COUNT(*) FROM crates".to_string()) + }); if needs_id { if id == -1 { @@ -608,15 +672,24 @@ pub fn index(req: &mut Request) -> CargoResult { // Query for the total count of crates let stmt = try!(conn.prepare(&cnt)); - let args = if args.len() > 2 {&args[..1]} else {&args[..0]}; + let args = if args.len() > 2 { + &args[..1] + } else { + &args[..0] + }; let rows = try!(stmt.query(args)); let row = rows.iter().next().unwrap(); let total = row.get(0); #[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, @@ -636,10 +709,12 @@ pub fn summary(req: &mut Request) -> CargoResult { let to_crates = |stmt: pg::stmt::Statement| -> CargoResult> { let rows = try!(stmt.query(&[])); - Ok(rows.iter().map(|r| { - let krate: Crate = Model::from_row(&r); - krate.minimal_encodable(None) - }).collect::>()) + Ok(rows.iter() + .map(|r| { + let krate: Crate = Model::from_row(&r); + krate.minimal_encodable(None) + }) + .collect::>()) }; let new_crates = try!(tx.prepare("SELECT * FROM crates \ ORDER BY created_at DESC LIMIT 10")); @@ -652,13 +727,13 @@ pub fn summary(req: &mut Request) -> CargoResult { let popular_keywords = try!(Keyword::all(tx, "crates", 10, 0)); let popular_keywords = popular_keywords.into_iter() - .map(Keyword::encodable) - .collect(); + .map(Keyword::encodable) + .collect(); let popular_categories = try!(Category::toplevel(tx, "crates", 10, 0)); let popular_categories = popular_categories.into_iter() - .map(Category::encodable) - .collect(); + .map(Category::encodable) + .collect(); #[derive(RustcEncodable)] struct R { @@ -700,12 +775,10 @@ pub fn show(req: &mut Request) -> CargoResult { categories: Vec, } Ok(req.json(&R { - krate: krate.clone().encodable( - Some(ids), Some(&kws), Some(&cats), Some(badges) - ), - versions: versions.into_iter().map(|v| { - v.encodable(&krate.name) - }).collect(), + krate: krate.clone().encodable(Some(ids), Some(&kws), Some(&cats), Some(badges)), + 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(), })) @@ -718,19 +791,26 @@ pub fn new(req: &mut Request) -> CargoResult { let (new_crate, user) = try!(parse_new_headers(req)); 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(|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(|s| &s[..]) + .unwrap_or(&[]); let keywords = keywords.iter().map(|k| k[..].to_string()).collect::>(); - let categories = new_crate.categories.as_ref().map(|s| &s[..]) - .unwrap_or(&[]); + let categories = new_crate.categories + .as_ref() + .map(|s| &s[..]) + .unwrap_or(&[]); let categories: Vec<_> = categories.iter().map(|k| k[..].to_string()).collect(); // Persist the new crate, if it doesn't already exist - let mut krate = try!(Crate::find_or_insert(try!(req.tx()), name, user.id, + let mut krate = try!(Crate::find_or_insert(try!(req.tx()), + name, + user.id, &new_crate.description, &new_crate.homepage, &new_crate.documentation, @@ -743,25 +823,23 @@ pub fn new(req: &mut Request) -> CargoResult { let owners = try!(krate.owners(try!(req.tx()))); if try!(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!("crate was previously named `{}`", krate.name))) + return Err(human(format!("crate was previously named `{}`", krate.name))); } - let length = try!(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 = try!(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!("max upload size is: {}", max))) + return Err(human(format!("max upload size is: {}", max))); } // Persist the new version of this crate - let mut version = try!(krate.add_version(try!(req.tx()), vers, &features, - &new_crate.authors)); + let mut version = try!(krate.add_version(try!(req.tx()), vers, &features, &new_crate.authors)); // Link this new version to all dependencies let mut deps = Vec::new(); @@ -775,19 +853,15 @@ pub fn new(req: &mut Request) -> CargoResult { // Update all categories for this crate, collecting any invalid categories // in order to be able to warn about them - let ignored_invalid_categories = try!( - Category::update_crate(try!(req.tx()), &krate, &categories) - ); + let ignored_invalid_categories = + try!(Category::update_crate(try!(req.tx()), &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 = try!( - Badge::update_crate( - try!(req.tx()), - &krate, - new_crate.badges.unwrap_or_else(HashMap::new) - ) - ); + let ignored_invalid_badges = try!(Badge::update_crate(try!(req.tx()), + &krate, + new_crate.badges + .unwrap_or_else(HashMap::new))); // Upload the crate to S3 let mut handle = req.app().handle(); @@ -798,28 +872,33 @@ pub fn new(req: &mut Request) -> CargoResult { let mut body = HashingReader::new(body); let mut response = Vec::new(); { - let mut s3req = app.bucket.put(&mut handle, &path, &mut body, + let mut s3req = app.bucket.put(&mut handle, + &path, + &mut body, "application/x-tar", length as u64); s3req.write_function(|data| { - response.extend(data); - Ok(data.len()) - }).unwrap(); - try!(s3req.perform().chain_error(|| { - internal(format!("failed to upload to S3: `{}`", path)) - })); + response.extend(data); + Ok(data.len()) + }) + .unwrap(); + try!(s3req.perform() + .chain_error(|| internal(format!("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!("failed to get a 200 response from S3: {}", - response))) + return Err(internal(format!("failed to get a 200 response from S3: {}", response))); } // If the git commands fail below, we shouldn't keep the crate on the // server. - struct Bomb { app: Arc, path: Option, handle: Easy } + struct Bomb { + app: Arc, + path: Option, + handle: Easy, + } impl Drop for Bomb { fn drop(&mut self) { if let Some(ref path) = self.path { @@ -827,7 +906,11 @@ pub fn new(req: &mut Request) -> CargoResult { } } } - let mut bomb = Bomb { app: app.clone(), path: Some(path), handle: handle }; + let mut bomb = Bomb { + app: app.clone(), + path: Some(path), + handle: handle, + }; // Register this crate in our local git repo. let git_crate = git::Crate { @@ -838,9 +921,8 @@ pub fn new(req: &mut Request) -> CargoResult { deps: deps, yanked: Some(false), }; - try!(git::add_crate(&**req.app(), &git_crate).chain_error(|| { - internal(format!("could not add crate `{}` to the git repo", name)) - })); + try!(git::add_crate(&**req.app(), &git_crate) + .chain_error(|| internal(format!("could not add crate `{}` to the git repo", name)))); // Now that we've come this far, we're committed! bomb.path = None; @@ -856,10 +938,13 @@ pub fn new(req: &mut Request) -> CargoResult { }; #[derive(RustcEncodable)] - struct R { krate: EncodableCrate, warnings: Warnings } + struct R { + krate: EncodableCrate, + warnings: Warnings, + } Ok(req.json(&R { krate: krate.minimal_encodable(None), - warnings: warnings + warnings: warnings, })) } @@ -868,19 +953,18 @@ fn parse_new_headers(req: &mut Request) -> CargoResult<(upload::NewCrate, User)> let amt = try!(read_le_u32(req.body())) as u64; let max = req.app().config.max_upload_size; if amt > max { - return Err(human(format!("max upload size is: {}", max))) + return Err(human(format!("max upload size is: {}", max))); } let mut json = vec![0; amt as usize]; try!(read_fill(req.body(), &mut json)); - let json = try!(String::from_utf8(json).map_err(|_| { - human("json body was not valid utf-8") - })); - let new: upload::NewCrate = try!(json::decode(&json).map_err(|e| { - human(format!("invalid upload request: {:?}", e)) - })); + let json = try!(String::from_utf8(json).map_err(|_| human("json body was not valid utf-8"))); + let new: upload::NewCrate = try!(json::decode(&json) + .map_err(|e| human(format!("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()) { @@ -895,7 +979,8 @@ fn parse_new_headers(req: &mut Request) -> CargoResult<(upload::NewCrate, User)> if missing.len() > 0 { return Err(human(format!("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 = try!(req.user()); @@ -905,19 +990,14 @@ fn parse_new_headers(req: &mut Request) -> CargoResult<(upload::NewCrate, User)> fn read_le_u32(r: &mut R) -> io::Result { let mut b = [0; 4]; try!(read_fill(r, &mut b)); - Ok(((b[0] as u32) << 0) | - ((b[1] as u32) << 8) | - ((b[2] as u32) << 16) | - ((b[3] as u32) << 24)) + Ok(((b[0] as u32) << 0) | ((b[1] as u32) << 8) | ((b[2] as u32) << 16) | ((b[3] as u32) << 24)) } -fn read_fill(r: &mut R, mut slice: &mut [u8]) - -> io::Result<()> { +fn read_fill(r: &mut R, mut slice: &mut [u8]) -> io::Result<()> { while slice.len() > 0 { let n = try!(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..]; } @@ -941,12 +1021,16 @@ pub fn download(req: &mut Request) -> CargoResult { let redirect_url = format!("https://{}/crates/{}/{}-{}.crate", req.app().bucket.host(), - crate_name, crate_name, version); + crate_name, + crate_name, + version); 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)) } @@ -963,9 +1047,7 @@ fn increment_download_counts(req: &Request, crate_name: &str, version: &str) -> AND versions.num = $2 LIMIT 1")); let rows = try!(stmt.query(&[&crate_name, &version])); - let row = try!(rows.iter().next().chain_error(|| { - human("crate or version not found") - })); + let row = try!(rows.iter().next().chain_error(|| human("crate or version not found"))); let version_id: i32 = row.get("version_id"); let now = ::now(); @@ -986,7 +1068,8 @@ fn increment_download_counts(req: &Request, crate_name: &str, version: &str) -> &[&version_id, &now])); if amt == 0 { try!(tx.execute("INSERT INTO version_downloads - (version_id) VALUES ($1)", &[&version_id])); + (version_id) VALUES ($1)", + &[&version_id])); } Ok(()) } @@ -1029,18 +1112,29 @@ pub fn downloads(req: &mut Request) -> CargoResult { for row in try!(stmt.query(&[&cutoff_date, &krate.id, &ids])).iter() { extra.push(ExtraDownload { downloads: row.get("downloads"), - date: row.get("date") + date: row.get("date"), }); } #[derive(RustcEncodable)] - 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, + })) } fn user_and_crate(req: &mut Request) -> CargoResult<(User, Crate)> { @@ -1060,10 +1154,13 @@ pub fn follow(req: &mut Request) -> CargoResult { let rows = try!(stmt.query(&[&user.id, &krate.id])); if !rows.iter().next().is_some() { try!(tx.execute("INSERT INTO follows (user_id, crate_id) - VALUES ($1, $2)", &[&user.id, &krate.id])); + VALUES ($1, $2)", + &[&user.id, &krate.id])); } #[derive(RustcEncodable)] - struct R { ok: bool } + struct R { + ok: bool, + } Ok(req.json(&R { ok: true })) } @@ -1075,7 +1172,9 @@ pub fn unfollow(req: &mut Request) -> CargoResult { WHERE user_id = $1 AND crate_id = $2", &[&user.id, &krate.id])); #[derive(RustcEncodable)] - struct R { ok: bool } + struct R { + ok: bool, + } Ok(req.json(&R { ok: true })) } @@ -1087,7 +1186,9 @@ pub fn following(req: &mut Request) -> CargoResult { WHERE user_id = $1 AND crate_id = $2")); let rows = try!(stmt.query(&[&user.id, &krate.id])); #[derive(RustcEncodable)] - struct R { following: bool } + struct R { + following: bool, + } Ok(req.json(&R { following: rows.iter().next().is_some() })) } @@ -1097,12 +1198,15 @@ pub fn versions(req: &mut Request) -> CargoResult { let tx = try!(req.tx()); let krate = try!(Crate::find_by_name(tx, crate_name)); let versions = try!(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. @@ -1114,8 +1218,10 @@ pub fn owners(req: &mut Request) -> CargoResult { let owners = owners.into_iter().map(|o| o.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. @@ -1152,33 +1258,32 @@ fn modify_owners(req: &mut Request, add: bool) -> CargoResult { owners: Option>, } - let request: Request = try!(json::decode(&body).map_err(|_| { - human("invalid json request") - })); + let request: Request = try!(json::decode(&body).map_err(|_| human("invalid json request"))); - let logins = try!(request.owners.or(request.users).ok_or_else(|| { - human("invalid json request") - })); + let logins = + try!(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!("`{}` is already an owner", login))) + return Err(human(format!("`{}` is already an owner", login))); } try!(krate.owner_add(req.app(), tx, &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")); } try!(krate.owner_remove(tx, &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. @@ -1193,8 +1298,16 @@ pub fn reverse_dependencies(req: &mut Request) -> CargoResult { .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 }, + })) } diff --git a/src/lib.rs b/src/lib.rs index f3efe3fedb2..bcaeda7ff88 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,8 @@ //! implemented in the [keyword](keyword/index.html), [krate](krate/index.html), //! [user](user/index.html) and [version](version/index.html) modules. -#[macro_use] extern crate log; +#[macro_use] +extern crate log; extern crate postgres as pg; extern crate rustc_serialize; extern crate curl; @@ -88,8 +89,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)); @@ -101,7 +104,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)); @@ -148,8 +152,7 @@ pub fn middleware(app: Arc) -> MiddlewareBuilder { m.around(util::Head::new()); 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); @@ -164,8 +167,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()); @@ -178,9 +180,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.iter() { diff --git a/src/owner.rs b/src/owner.rs index 62363d73892..5ebaed07e27 100644 --- a/src/owner.rs +++ b/src/owner.rs @@ -34,7 +34,6 @@ pub struct Team { /// Sugary goodness pub name: Option, pub avatar: Option, - } #[derive(RustcEncodable)] @@ -59,14 +58,11 @@ pub enum Rights { impl Team { /// Just gets the Team from the database by name. - pub fn find_by_login(conn: &GenericConnection, - login: &str) -> CargoResult { + pub fn find_by_login(conn: &GenericConnection, login: &str) -> CargoResult { let stmt = try!(conn.prepare("SELECT * FROM teams WHERE login = $1")); let rows = try!(stmt.query(&[&login])); - let row = try!(rows.iter().next().chain_error(|| { - NotFound - })); + let row = try!(rows.iter().next().chain_error(|| NotFound)); Ok(Model::from_row(&row)) } @@ -83,24 +79,25 @@ impl Team { "github" => { // Ok to unwrap since we know one ":" is contained let org = chunks.next().unwrap(); - let team = try!(chunks.next().ok_or_else(|| + let team = try!(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")), } } /// 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: &GenericConnection, login: &str, - org_name: &str, team_name: &str, req_user: &User) + pub fn create_github_team(app: &App, + conn: &GenericConnection, + 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 @@ -109,20 +106,21 @@ 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!("organization cannot contain special \ - characters like {}", c))); + 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 @@ -132,12 +130,11 @@ impl Team { let (handle, data) = try!(http::github(app, &url, &token)); let teams: Vec = try!(http::parse_github_response(handle, data)); - let team = try!(teams.into_iter().find(|team| team.slug == team_name) - .ok_or_else(||{ - human(format!("could not find the github team {}/{}", - org_name, team_name)) - }) - ); + let team = try!(teams.into_iter() + .find(|team| team.slug == team_name) + .ok_or_else(|| { + human(format!("could not find the github team {}/{}", org_name, team_name)) + })); if !try!(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,8 +178,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" @@ -191,14 +187,13 @@ fn team_with_gh_id_contains_user(app: &App, github_id: i32, user: &User) 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) = try!(http::github(app, &url, &token)); // Officially how `false` is returned if handle.response_code().unwrap() == 404 { - return Ok(false) + return Ok(false); } let membership: Membership = try!(http::parse_github_response(handle, resp)); @@ -219,23 +214,22 @@ 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: &GenericConnection, - name: &str) -> CargoResult { + pub fn find_by_login(conn: &GenericConnection, name: &str) -> CargoResult { let owner = if name.contains(":") { - Owner::Team(try!(Team::find_by_login(conn, name).map_err(|_| - human(format!("could not find team with name {}", name)) - ))) + Owner::Team(try!(Team::find_by_login(conn, name) + .map_err(|_| human(format!("could not find team with name {}", name))))) } else { - Owner::User(try!(User::find_by_login(conn, name).map_err(|_| - human(format!("could not find user with login `{}`", name)) - ))) + Owner::User(try!(User::find_by_login(conn, name) + .map_err(|_| human(format!("could not find user with login `{}`", name))))) }; Ok(owner) } @@ -280,7 +274,8 @@ impl Owner { let mut parts = login.split(":"); parts.next(); // discard github format!("https://github.com/orgs/{}/teams/{}", - parts.next().unwrap(), parts.next().unwrap()) + parts.next().unwrap(), + parts.next().unwrap()) }; EncodableOwner { id: id, @@ -308,14 +303,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 try!(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 try!(team.contains_user(app, user)) { + best = Rights::Publish; + } + } } } Ok(best) } - diff --git a/src/tests/all.rs b/src/tests/all.rs old mode 100755 new mode 100644 index a008de37d67..3f0371e0b14 --- a/src/tests/all.rs +++ b/src/tests/all.rs @@ -59,9 +59,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; @@ -107,8 +111,10 @@ fn app() -> (record::Bomb, Arc, conduit_middleware::MiddlewareBuilder) { me.pop(); } me.push("migrate"); - assert!(t!(Command::new(&me).env("DATABASE_URL", db) - .status()).success()); + assert!(t!(Command::new(&me) + .env("DATABASE_URL", db) + .status()) + .success()); } } @@ -131,7 +137,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,18 +162,14 @@ fn json(r: &mut conduit::Response) -> T { 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, } } @@ -212,7 +216,8 @@ fn mock_user(req: &mut Request, u: User) -> User { u.name.as_ref().map(|s| &s[..]), u.avatar.as_ref().map(|s| &s[..]), &u.gh_access_token, - &u.api_token).unwrap(); + &u.api_token) + .unwrap(); req.mut_extensions().insert(u.clone()); return u; } @@ -221,31 +226,39 @@ 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()) } -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 mock_keyword(req: &mut Request, name: &str) -> Keyword { @@ -254,10 +267,8 @@ fn mock_keyword(req: &mut Request, name: &str) -> Keyword { 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(); + let stmt = conn.prepare(" INSERT INTO categories (category, slug) VALUES ($1, $2) RETURNING *") + .unwrap(); let rows = stmt.query(&[&name, &slug]).unwrap(); Model::from_row(&rows.iter().next().unwrap()) } @@ -270,89 +281,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() - ) + 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 { +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 6715590cee4..62c599c9d66 100644 --- a/src/tests/badge.rs +++ b/src/tests/badge.rs @@ -17,7 +17,9 @@ struct BadgeRef { gitlab_attributes: HashMap, } -fn tx(req: &Request) -> &GenericConnection { req.tx().unwrap() } +fn tx(req: &Request) -> &GenericConnection { + req.tx().unwrap() +} fn set_up() -> (MockRequest, Crate, BadgeRef) { let (_b, app, _middle) = ::app(); @@ -32,42 +34,24 @@ fn set_up() -> (MockRequest, 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 badges = BadgeRef { appveyor: appveyor, @@ -98,10 +82,7 @@ fn update_add_appveyor() { let (req, krate, test_badges) = set_up(); 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(tx(&req), &krate, badges).unwrap(); assert_eq!(krate.badges(tx(&req)).unwrap(), vec![test_badges.appveyor]); } @@ -112,10 +93,7 @@ fn update_add_travis_ci() { let (req, krate, test_badges) = set_up(); 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(tx(&req), &krate, badges).unwrap(); assert_eq!(krate.badges(tx(&req)).unwrap(), vec![test_badges.travis_ci]); } @@ -126,10 +104,7 @@ fn update_add_gitlab() { let (req, krate, test_badges) = set_up(); 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(tx(&req), &krate, badges).unwrap(); assert_eq!(krate.badges(tx(&req)).unwrap(), vec![test_badges.gitlab]); } @@ -141,19 +116,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(tx(&req), &krate, badges.clone()).unwrap(); assert_eq!(krate.badges(tx(&req)).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(tx(&req), &krate, badges).unwrap(); assert_eq!(krate.badges(tx(&req)).unwrap(), vec![test_badges.travis_ci]); } @@ -165,10 +135,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(tx(&req), &krate, badges).unwrap(); let current_badges = krate.badges(tx(&req)).unwrap(); assert_eq!(current_badges.len(), 1); @@ -181,14 +148,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(tx(&req), &krate, badges).unwrap(); let current_badges = krate.badges(tx(&req)).unwrap(); assert_eq!(current_badges.len(), 1); @@ -203,18 +165,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(tx(&req), &krate, badges.clone()).unwrap(); let current_badges = krate.badges(tx(&req)).unwrap(); @@ -238,14 +191,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(tx(&req), &krate, badges).unwrap(); assert_eq!(krate.badges(tx(&req)).unwrap(), vec![test_badges.appveyor]); @@ -260,10 +207,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(tx(&req), &krate, badges).unwrap(); assert_eq!(invalid_badges.len(), 1); @@ -280,10 +224,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(tx(&req), &krate, badges).unwrap(); assert_eq!(invalid_badges.len(), 1); @@ -300,14 +241,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(tx(&req), &krate, badges).unwrap(); assert_eq!(invalid_badges.len(), 1); diff --git a/src/tests/category.rs b/src/tests/category.rs index 3771397b9de..963b21520d5 100644 --- a/src/tests/category.rs +++ b/src/tests/category.rs @@ -6,14 +6,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] @@ -62,7 +69,9 @@ fn show() { assert_eq!(json.category.subcategories[0].category, "Foo Bar::Baz"); } -fn tx(req: &Request) -> &GenericConnection { req.tx().unwrap() } +fn tx(req: &Request) -> &GenericConnection { + req.tx().unwrap() +} #[test] fn update_crate() { @@ -89,9 +98,7 @@ fn update_crate() { assert_eq!(cnt(&mut req, "category-2"), 0); // Replacing one category with another - Category::update_crate( - tx(&req), &krate, &["category-2".to_string()] - ).unwrap(); + Category::update_crate(tx(&req), &krate, &["category-2".to_string()]).unwrap(); assert_eq!(cnt(&mut req, "cat1"), 0); assert_eq!(cnt(&mut req, "category-2"), 1); @@ -101,9 +108,10 @@ fn update_crate() { assert_eq!(cnt(&mut req, "category-2"), 0); // Adding 2 categories - Category::update_crate( - tx(&req), &krate, &["cat1".to_string(), - "category-2".to_string()]).unwrap(); + Category::update_crate(tx(&req), + &krate, + &["cat1".to_string(), "category-2".to_string()]) + .unwrap(); assert_eq!(cnt(&mut req, "cat1"), 1); assert_eq!(cnt(&mut req, "category-2"), 1); @@ -113,10 +121,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( - tx(&req), &krate, &["cat1".to_string(), - "catnope".to_string()] - ).unwrap(); + let invalid_categories = Category::update_crate(tx(&req), + &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); @@ -130,17 +138,16 @@ fn update_crate() { assert_eq!(json.meta.total, 2); // Attempting to add a category by display text; must use slug - Category::update_crate( - tx(&req), &krate, &["Category 2".to_string()] - ).unwrap(); + Category::update_crate(tx(&req), &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( - tx(&req), &krate, &["cat1".to_string(), - "cat1::bar".to_string()]).unwrap(); + Category::update_crate(tx(&req), + &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..00afbe61eb3 100644 --- a/src/tests/git.rs +++ b/src/tests/git.rs @@ -11,17 +11,19 @@ fn root() -> PathBuf { 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 { @@ -48,9 +50,8 @@ 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 c1f50bf38f6..acac10b69ca 100644 --- a/src/tests/keyword.rs +++ b/src/tests/keyword.rs @@ -6,11 +6,18 @@ use cargo_registry::db::RequestTransaction; 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() { @@ -53,7 +60,9 @@ fn uppercase() { assert_eq!(json.keyword.keyword, "upper".to_string()); } -fn tx(req: &Request) -> &GenericConnection { req.tx().unwrap() } +fn tx(req: &Request) -> &GenericConnection { + req.tx().unwrap() +} #[test] fn update_crate() { @@ -85,8 +94,7 @@ fn update_crate() { assert_eq!(cnt(&mut req, "kw1"), 0); assert_eq!(cnt(&mut req, "kw2"), 0); - Keyword::update_crate(tx(&req), &krate, &["kw1".to_string(), - "kw2".to_string()]).unwrap(); + Keyword::update_crate(tx(&req), &krate, &["kw1".to_string(), "kw2".to_string()]).unwrap(); assert_eq!(cnt(&mut req, "kw1"), 1); assert_eq!(cnt(&mut req, "kw2"), 1); diff --git a/src/tests/krate.rs b/src/tests/krate.rs index 8b60d8b77ef..979d98344da 100644 --- a/src/tests/krate.rs +++ b/src/tests/krate.rs @@ -20,25 +20,54 @@ 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 GitCrate { name: String, vers: String, deps: Vec, cksum: String } +struct GitCrate { + name: String, + vers: String, + deps: Vec, + cksum: String, +} #[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 { @@ -80,7 +109,9 @@ fn index() { assert_eq!(json.crates[0].id, krate.name); } -fn tx(req: &Request) -> &GenericConnection { req.tx().unwrap() } +fn tx(req: &Request) -> &GenericConnection { + req.tx().unwrap() +} #[test] fn index_queries() { @@ -134,8 +165,10 @@ fn index_queries() { ::mock_category(&mut req, "cat1", "cat1"); ::mock_category(&mut req, "cat1::bar", "cat1::bar"); - Category::update_crate(tx(&req), &krate, &["cat1".to_string(), - "cat1::bar".to_string()]).unwrap(); + Category::update_crate(tx(&req), + &krate, + &["cat1".to_string(), "cat1::bar".to_string()]) + .unwrap(); let mut response = ok_resp!(middle.call(req.with_query("category=cat1"))); let cl = ::json::(&mut response); assert_eq!(cl.crates.len(), 1); @@ -163,7 +196,8 @@ fn exact_match_first_on_queries() { krate2.description = Some("foo_exact baz_exact foo_exact baz_exact".to_string()); let (_, _) = ::mock_crate(&mut req, krate2.clone()); let mut krate3 = ::krate("baz_exact"); - krate3.description = Some("foo_exact bar_exact foo_exact bar_exact foo_exact bar_exact".to_string()); + krate3.description = Some("foo_exact bar_exact foo_exact bar_exact foo_exact bar_exact" + .to_string()); let (_, _) = ::mock_crate(&mut req, krate3.clone()); let mut krate4 = ::krate("other_exact"); krate4.description = Some("other_exact".to_string()); @@ -206,7 +240,8 @@ fn exact_match_on_queries_with_sort() { krate2.downloads = 3333; let (k2, _) = ::mock_crate(&mut req, krate2.clone()); let mut krate3 = ::krate("baz_sort"); - krate3.description = Some("foo_sort bar_sort foo_sort bar_sort foo_sort bar_sort const".to_string()); + krate3.description = Some("foo_sort bar_sort foo_sort bar_sort foo_sort bar_sort const" + .to_string()); krate3.downloads = 100000; let (k3, _) = ::mock_crate(&mut req, krate3.clone()); let mut krate4 = ::krate("other_sort"); @@ -218,13 +253,21 @@ fn exact_match_on_queries_with_sort() { let req2: &mut Request = &mut req; let tx = req2.tx().unwrap(); tx.execute("UPDATE crates set downloads = $1 - WHERE id = $2", &[&krate.downloads, &k.id]).unwrap(); + WHERE id = $2", + &[&krate.downloads, &k.id]) + .unwrap(); tx.execute("UPDATE crates set downloads = $1 - WHERE id = $2", &[&krate2.downloads, &k2.id]).unwrap(); + WHERE id = $2", + &[&krate2.downloads, &k2.id]) + .unwrap(); tx.execute("UPDATE crates set downloads = $1 - WHERE id = $2", &[&krate3.downloads, &k3.id]).unwrap(); + WHERE id = $2", + &[&krate3.downloads, &k3.id]) + .unwrap(); tx.execute("UPDATE crates set downloads = $1 - WHERE id = $2", &[&krate4.downloads, &k4.id]).unwrap(); + WHERE id = $2", + &[&krate4.downloads, &k4.id]) + .unwrap(); } let mut response = ok_resp!(middle.call(req.with_query("q=foo_sort&sort=downloads"))); @@ -285,7 +328,8 @@ fn show() { assert_eq!(json.versions[0].num, "1.0.0".to_string()); 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".to_string(), json.keywords[0].id); } @@ -330,7 +374,8 @@ fn new_bad_names() { ::logout(&mut req); let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("invalid crate name"), - "{:?}", json.errors); + "{:?}", + json.errors); } bad_name(""); @@ -398,7 +443,9 @@ fn new_krate_with_wildcard_dependency() { ::mock_user(&mut req, ::user("foo")); ::mock_crate(&mut req, ::krate("foo_wild")); 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] @@ -430,7 +477,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] @@ -442,20 +490,25 @@ fn new_krate_bad_name() { ::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); } { let mut req = ::new_req(app, "áccênts", "2.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); + "{:?}", + json.errors); } } #[test] fn new_crate_owner() { - #[derive(RustcDecodable)] struct O { ok: bool } + #[derive(RustcDecodable)] + struct O { + ok: bool, + } let (_b, app, middle) = ::app(); @@ -469,26 +522,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")); req.mut_extensions().insert(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); } @@ -531,7 +584,8 @@ fn new_krate_duplicate_version() { ::mock_crate(&mut req, ::krate("foo_dupe")); let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("already uploaded"), - "{:?}", json.errors); + "{:?}", + json.errors); } #[test] @@ -542,7 +596,8 @@ fn new_crate_similar_name() { ::mock_crate(&mut req, ::krate("Foo_similar")); let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("previously named"), - "{:?}", json.errors); + "{:?}", + json.errors); } #[test] @@ -554,7 +609,8 @@ fn new_crate_similar_name_hyphen() { ::mock_crate(&mut req, ::krate("foo_bar_hyphen")); let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("previously named"), - "{:?}", json.errors); + "{:?}", + json.errors); } { let (_b, app, middle) = ::app(); @@ -563,7 +619,8 @@ fn new_crate_similar_name_hyphen() { ::mock_crate(&mut req, ::krate("foo-bar-underscore")); let json = bad_resp!(middle.call(&mut req)); assert!(json.errors[0].detail.contains("previously named"), - "{:?}", json.errors); + "{:?}", + json.errors); } } @@ -592,9 +649,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":[],"cksum":"3j3"} -"#).unwrap(); + File::create(&path) + .unwrap() + .write_all(br#"{"name":"FPP","vers":"0.0.1","deps":[],"cksum":"3j3"} +"#) + .unwrap(); let mut req = ::new_req(app, "FPP", "1.0.0"); ::mock_user(&mut req, ::user("foo")); @@ -625,8 +684,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, "foo_conflicts", "1.0.0"); @@ -651,8 +710,9 @@ fn new_krate_dependency_missing() { ::mock_user(&mut req, ::user("foo")); 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] @@ -665,7 +725,9 @@ fn summary_doesnt_die() { #[test] fn download() { let (_b, app, middle) = ::app(); - let mut req = ::req(app, Method::Get, "/api/v1/crates/foo_download/1.0.0/download"); + let mut req = ::req(app, + Method::Get, + "/api/v1/crates/foo_download/1.0.0/download"); ::mock_user(&mut req, ::user("foo")); ::mock_crate(&mut req, ::krate("foo_download")); let resp = t_resp!(middle.call(&mut req)); @@ -700,7 +762,9 @@ fn download_bad() { fn dependencies() { let (_b, app, middle) = ::app(); - let mut req = ::req(app, Method::Get, "/api/v1/crates/foo_deps/1.0.0/dependencies"); + let mut req = ::req(app, + Method::Get, + "/api/v1/crates/foo_deps/1.0.0/dependencies"); ::mock_user(&mut req, ::user("foo")); let (_, v) = ::mock_crate(&mut req, ::krate("foo_deps")); let (c, _) = ::mock_crate(&mut req, ::krate("bar_deps")); @@ -717,8 +781,14 @@ fn dependencies() { #[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, Method::Get, "/api/v1/crates/foo_following/following"); @@ -729,46 +799,52 @@ 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); req.with_path("/api/v1/crates") - .with_query("following=1"); + .with_query("following=1"); let mut response = ok_resp!(middle.call(&mut req)); let l = ::json::(&mut response); 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, Method::Get, "/api/v1/crates/foo_owners/owners"); @@ -787,7 +863,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))); @@ -796,7 +872,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))); @@ -805,19 +881,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"); @@ -832,29 +914,29 @@ fn yank() { // 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(); 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(); 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); } @@ -940,10 +1022,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(); @@ -956,19 +1036,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(), - &String::from("rust-lang/crates.io") - ); + assert_eq!(badges[0].attributes.get("repository").unwrap(), + &String::from("rust-lang/crates.io")); } #[test] @@ -978,18 +1055,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(); @@ -1005,9 +1076,8 @@ fn ignored_badges() { 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); @@ -1021,8 +1091,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); @@ -1061,7 +1130,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()); @@ -1070,7 +1140,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()); @@ -1080,6 +1151,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 04c66e887b9..a8d02398ecf 100644 --- a/src/tests/record.rs +++ b/src/tests/record.rs @@ -36,7 +36,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 { @@ -44,12 +46,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) @@ -80,10 +81,12 @@ 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() { @@ -111,7 +114,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) { @@ -123,7 +132,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(), @@ -144,7 +154,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)); } @@ -172,9 +182,7 @@ fn record_http(mut socket: TcpStream, data: &mut BufStream) { response.extend(data); Ok(data.len()) })); - t!(transfer.read_function(|buf| { - socket.read(buf).map_err(|_| ReadError::Abort) - })); + t!(transfer.read_function(|buf| socket.read(buf).map_err(|_| ReadError::Abort))); t!(transfer.perform()); } @@ -182,15 +190,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")); @@ -200,8 +204,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,21 +221,33 @@ fn replay_http(socket: TcpStream, data: &mut BufStream, // validate the headers let mut expected: HashSet = expected_lines.by_ref() - .take_while(|l| l.len() > 2) - .collect(); + .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); } @@ -246,10 +261,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(); } @@ -261,22 +277,25 @@ impl GhUser { self.init.call_once(|| self.init()); let mut u = ::user(self.login); u.gh_access_token = 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 + 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,13 +305,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)); @@ -305,9 +326,7 @@ 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()) @@ -316,15 +335,17 @@ impl GhUser { } 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 de5b43f41d8..12539209bfa 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() -> User { GH_USER_1.user() } -fn mock_user_on_x_and_y() -> User { 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() -> User { + GH_USER_1.user() +} +fn mock_user_on_x_and_y() -> User { + GH_USER_2.user() +} fn body_for_team_y() -> &'static str { r#"{"users":["github:crates-test-org:just-for-crates-2"]}"# @@ -33,10 +43,11 @@ fn 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] @@ -48,10 +59,11 @@ fn 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()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); assert!(json.errors[0].detail.contains("organization cannot contain"), - "{:?}", json.errors); + "{:?}", + json.errors); } // Test adding team without second `:` @@ -64,10 +76,11 @@ fn 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] @@ -79,10 +92,11 @@ fn nonexistent_team() { 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()))); + .with_method(Method::Put) + .with_body(body.as_bytes()))); assert!(json.errors[0].detail.contains("could not find the github team"), - "{:?}", json.errors); + "{:?}", + json.errors); } // Test adding team as owner when on it @@ -95,8 +109,8 @@ fn add_team_as_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 @@ -109,10 +123,11 @@ fn add_team_as_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 removing team as named owner @@ -125,21 +140,22 @@ fn remove_team_as_named_owner() { 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()))); ::mock_user(&mut req, mock_user_on_only_x()); 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 removing team as team owner @@ -152,22 +168,23 @@ fn remove_team_as_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()))); ::mock_user(&mut req, mock_user_on_only_x()); 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 @@ -181,16 +198,17 @@ fn publish_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()))); ::mock_user(&mut req, mock_user_on_only_x()); 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) @@ -203,14 +221,14 @@ fn publish_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()))); ::mock_user(&mut req, mock_user_on_only_x()); 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) @@ -223,15 +241,15 @@ fn add_owners_as_team_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()))); ::mock_user(&mut req, mock_user_on_only_x()); - 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 e10a8ddd425..92130778478 100644 --- a/src/tests/user.rs +++ b/src/tests/user.rs @@ -7,9 +7,15 @@ use cargo_registry::db::RequestTransaction; 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, +} #[test] fn auth_gives_a_token() { @@ -39,16 +45,14 @@ fn user_insert() { assert_eq!(t!(User::find_by_api_token(&tx, "baz")), user); assert_eq!(t!(User::find(&tx, user.id)), user); - assert_eq!(t!(User::find_or_insert(&tx, 1, "foo", None, None, None, - "bar", "api")), user); - let user2 = t!(User::find_or_insert(&tx, 1, "foo", None, None, None, - "baz", "api")); + assert_eq!(t!(User::find_or_insert(&tx, 1, "foo", None, None, None, "bar", "api")), + user); + let user2 = t!(User::find_or_insert(&tx, 1, "foo", None, None, None, "baz", "api")); 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", "api")); + let user3 = t!(User::find_or_insert(&tx, 1, "bar", None, None, None, "baz", "api")); assert!(user != user3); assert_eq!(user.id, user3.id); assert_eq!(user3.gh_login, "bar"); @@ -75,8 +79,7 @@ fn reset_token() { let mut req = ::req(app, Method::Put, "/me/reset_token"); let user = { let tx = RequestTransaction::tx(&mut req as &mut Request); - User::find_or_insert(tx.unwrap(), 1, "foo", None, - None, None, "bar", "baz").unwrap() + User::find_or_insert(tx.unwrap(), 1, "foo", None, None, None, "bar", "baz").unwrap() }; ::mock_user(&mut req, user.clone()); ok_resp!(middle.call(&mut req)); @@ -96,7 +99,9 @@ fn my_packages() { 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); } @@ -108,7 +113,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, Method::Get, "/"); @@ -117,34 +125,34 @@ fn following() { ::mock_crate(&mut req, ::krate("bar_fighters")); let mut response = ok_resp!(middle.call(req.with_path("/me/updates") - .with_method(Method::Get))); + .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))); + .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 5e4b13c7de5..75ee2e5e1f3 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() diff --git a/src/upload.rs b/src/upload.rs index 3a775645f6e..3b627a14366 100644 --- a/src/upload.rs +++ b/src/upload.rs @@ -52,7 +52,7 @@ impl Decodable for CrateName { fn decode(d: &mut D) -> Result { let s = try!(d.read_str()); if !Crate::valid_name(&s) { - return Err(d.error(&format!("invalid crate name specified: {}", s))) + return Err(d.error(&format!("invalid crate name specified: {}", s))); } Ok(CrateName(s)) } @@ -62,7 +62,7 @@ impl Decodable for Keyword { fn decode(d: &mut D) -> Result { let s = try!(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)) } @@ -78,7 +78,7 @@ impl Decodable for Feature { fn decode(d: &mut D) -> Result { let s = try!(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)) } @@ -108,12 +108,12 @@ impl Decodable for KeywordList { fn decode(d: &mut D) -> Result { let inner: Vec = try!(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.iter() { if val.len() > 20 { return Err(d.error("keywords must contain less than 20 \ - characters")) + characters")); } } Ok(KeywordList(inner)) @@ -124,7 +124,7 @@ impl Decodable for CategoryList { fn decode(d: &mut D) -> Result { let inner: Vec = try!(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)) } @@ -137,8 +137,11 @@ 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))) + } } } } @@ -205,44 +208,58 @@ 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<'a>(&'a self) -> &'a semver::Version { - let CrateVersion(ref s) = *self; s + let CrateVersion(ref s) = *self; + s } } impl Deref for CrateVersionReq { type Target = semver::VersionReq; fn deref<'a>(&'a self) -> &'a semver::VersionReq { - let CrateVersionReq(ref s) = *self; s + let CrateVersionReq(ref s) = *self; + s } } 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/user/middleware.rs b/src/user/middleware.rs index 2e6265e0085..fcb8de0bd87 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 = try!(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(()), } } }; diff --git a/src/user/mod.rs b/src/user/mod.rs index 8e9bdf1e928..b3e7b5987e7 100644 --- a/src/user/mod.rs +++ b/src/user/mod.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use conduit::{Request, Response}; -use conduit_cookie::{RequestSession}; +use conduit_cookie::RequestSession; use conduit_router::RequestParams; use pg::GenericConnection; use pg::rows::Row; @@ -45,26 +45,20 @@ 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 = try!(conn.prepare("SELECT * FROM users WHERE gh_login = $1")); let rows = try!(stmt.query(&[&login])); - let row = try!(rows.iter().next().chain_error(|| { - NotFound - })); + let row = try!(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 = try!(conn.prepare("SELECT * FROM users \ WHERE api_token = $1 LIMIT 1")); let rows = try!(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. @@ -75,7 +69,8 @@ impl User { name: Option<&str>, avatar: Option<&str>, access_token: &str, - api_token: &str) -> CargoResult { + api_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. @@ -88,12 +83,7 @@ impl User { gh_login = $5 WHERE gh_id = $6 RETURNING *")); - let rows = try!(stmt.query(&[&access_token, - &email, - &name, - &avatar, - &login, - &id])); + let rows = try!(stmt.query(&[&access_token, &email, &name, &avatar, &login, &id])); match rows.iter().next() { Some(ref row) => return Ok(Model::from_row(row)), None => {} @@ -103,16 +93,11 @@ impl User { gh_login, name, gh_avatar, gh_id) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING *")); - let rows = try!(stmt.query(&[&email, - &access_token, - &api_token, - &login, - &name, - &avatar, - &id])); - Ok(Model::from_row(&try!(rows.iter().next().chain_error(|| { - internal("no user with email we just found") - })))) + let rows = + try!(stmt.query(&[&email, &access_token, &api_token, &login, &name, &avatar, &id])); + Ok(Model::from_row(&try!(rows.iter() + .next() + .chain_error(|| internal("no user with email we just found"))))) } /// Generates a new crates.io API token. @@ -148,7 +133,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. @@ -174,8 +161,14 @@ pub fn github_authorize(req: &mut Request) -> CargoResult { 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. @@ -218,7 +211,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")); } } @@ -245,12 +238,15 @@ pub fn github_access_token(req: &mut Request) -> CargoResult { let user = try!(User::find_or_insert(try!(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, &api_token)); req.session().insert("user_id".to_string(), user.id.to_string()); @@ -274,7 +270,9 @@ pub fn reset_token(req: &mut Request) -> CargoResult { &[&token, &user.id])); #[derive(RustcEncodable)] - struct R { api_token: String } + struct R { + api_token: String, + } Ok(req.json(&R { api_token: token })) } @@ -283,9 +281,15 @@ pub fn me(req: &mut Request) -> CargoResult { let user = try!(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. @@ -298,7 +302,7 @@ pub fn show(req: &mut Request) -> CargoResult { struct R { user: EncodableUser, } - Ok(req.json(&R{ user: user.clone().encodable() })) + Ok(req.json(&R { user: user.clone().encodable() })) } @@ -336,19 +340,23 @@ pub fn updates(req: &mut Request) -> CargoResult { } // Encode everything! - let crates = crates.into_iter().map(|c| { - c.minimal_encodable(None) - }).collect(); - let versions = versions.into_iter().map(|v| { - let id = v.crate_id; - v.encodable(&map[&id]) - }).collect(); + let crates = crates.into_iter() + .map(|c| c.minimal_encodable(None)) + .collect(); + let versions = versions.into_iter() + .map(|v| { + let id = v.crate_id; + v.encodable(&map[&id]) + }) + .collect(); // Check if we have another let sql = format!("SELECT 1 WHERE EXISTS({})", sql); let stmt = try!(tx.prepare(&sql)); let more = try!(stmt.query(&[&user.id, &(offset + limit), &limit])) - .iter().next().is_some(); + .iter() + .next() + .is_some(); #[derive(RustcEncodable)] struct R { @@ -357,6 +365,12 @@ pub fn updates(req: &mut Request) -> CargoResult { meta: Meta, } #[derive(RustcEncodable)] - struct Meta { more: bool } - Ok(req.json(&R{ versions: versions, crates: crates, meta: Meta { more: more } })) + struct Meta { + more: bool, + } + Ok(req.json(&R { + versions: versions, + crates: crates, + meta: Meta { more: more }, + })) } diff --git a/src/util/errors.rs b/src/util/errors.rs index 8c78b86a79b..535dd5f4bdd 100644 --- a/src/util/errors.rs +++ b/src/util/errors.rs @@ -5,26 +5,36 @@ use conduit::Response; 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<'a>(&'a self) -> Option<&'a (CargoError)> { None } + fn cause<'a>(&'a self) -> Option<&'a (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 { @@ -34,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>; @@ -53,7 +79,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 { @@ -61,9 +88,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) } } @@ -71,7 +102,9 @@ 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(), @@ -83,7 +116,9 @@ impl ChainError for Result { 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())), @@ -92,10 +127,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 { @@ -111,7 +154,9 @@ impl From for Box { fn from(err: E) -> 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 { @@ -123,10 +168,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) + } } // ============================================================================= @@ -142,7 +191,7 @@ struct ConcreteCargoError { impl fmt::Display for ConcreteCargoError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "{}", self.description)); - match self.detail { + match self.detail { Some(ref s) => try!(write!(f, " ({})", s)), None => {} } @@ -151,20 +200,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"); return Some(response); } @@ -179,13 +235,15 @@ 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 { - detail: "must be logged in to perform that action".to_string(), - }], + detail: "must be logged in to perform that action".to_string(), + }], }); response.status = (403, "Forbidden"); return Some(response); @@ -225,11 +283,13 @@ pub fn human(error: S) -> Box { }) } -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/hasher.rs b/src/util/hasher.rs index 9f8def19d6a..3f0ac9bd488 100644 --- a/src/util/hasher.rs +++ b/src/util/hasher.rs @@ -24,6 +24,6 @@ impl Read for HashingReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { let amt = try!(self.inner.read(buf)); self.hasher.update(&buf[..amt]).unwrap(); - return Ok(amt) + return Ok(amt); } } diff --git a/src/util/head.rs b/src/util/head.rs index 6a3547d66dc..b93591c8908 100644 --- a/src/util/head.rs +++ b/src/util/head.rs @@ -23,19 +23,18 @@ 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 b780acebf62..e54bd9fa5c2 100644 --- a/src/util/io_util.rs +++ b/src/util/io_util.rs @@ -15,8 +15,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, } 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 663f0905339..062de9c179c 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; pub use self::lazy_cell::LazyCell; @@ -52,18 +52,14 @@ pub fn json_response(t: &T) -> Response { 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 +72,9 @@ 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,25 @@ 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!("cannot request more than {} items", max))) + return Err(human(format!("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 +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) => { @@ -127,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)), } } } @@ -137,7 +137,7 @@ 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 { @@ -151,7 +151,7 @@ impl Handler for R { 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 92dd267cc61..9e46fc10288 100644 --- a/src/util/request_proxy.rs +++ b/src/util/request_proxy.rs @@ -21,8 +21,12 @@ impl<'a> Request for RequestProxy<'a> { fn method(&self) -> conduit::Method { self.method.unwrap_or(self.other.method()) } - 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 +36,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 98c27b758b8..6518592fa2e 100644 --- a/src/version.rs +++ b/src/version.rs @@ -79,14 +79,13 @@ impl Version { -> CargoResult { let num = num.to_string(); let features = json::encode(features).unwrap(); - let stmt = try!(conn.prepare("INSERT INTO versions \ - (crate_id, num, features) \ - VALUES ($1, $2, $3) \ - RETURNING *")); + let stmt = + try!(conn.prepare("INSERT INTO versions (crate_id, num, features) VALUES ($1, $2, $3) \ + RETURNING *")); let rows = try!(stmt.query(&[&crate_id, &num, &features])); - let ret: Version = Model::from_row(&try!(rows.iter().next().chain_error(|| { - internal("no version returned") - }))); + let ret: Version = Model::from_row(&try!(rows.iter() + .next() + .chain_error(|| internal("no version returned")))); for author in authors.iter() { try!(ret.add_author(conn, &author)); } @@ -112,10 +111,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), }, } @@ -128,19 +125,22 @@ impl Version { dep: &upload::CrateDependency) -> CargoResult<(Dependency, Crate)> { let name = &dep.name; - let krate = try!(Crate::find_by_name(conn, name).map_err(|_| { - human(format!("no known crate named `{}`", &**name)) - })); + let krate = try!(Crate::find_by_name(conn, name) + .map_err(|_| human(format!("no known crate named `{}`", &**name)))); if dep.version_req.0 == semver::VersionReq::parse("*").unwrap() { - return Err(human(format!("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"))); + return Err(human(format!("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[..].to_string() - }).collect(); - let dep = try!(Dependency::insert(conn, self.id, krate.id, + let features: Vec = dep.features + .iter() + .map(|s| s[..].to_string()) + .collect(); + let dep = try!(Dependency::insert(conn, + self.id, + krate.id, &*dep.version_req, dep.kind.unwrap_or(Kind::Normal), dep.optional, @@ -151,8 +151,7 @@ impl Version { } /// Returns (dependency, crate dependency name) - pub fn dependencies(&self, conn: &GenericConnection) - -> CargoResult> { + pub fn dependencies(&self, conn: &GenericConnection) -> CargoResult> { let stmt = try!(conn.prepare("SELECT dependencies.*, crates.name AS crate_name FROM dependencies @@ -160,32 +159,33 @@ impl Version { ON crates.id = dependencies.crate_id WHERE dependencies.version_id = $1")); let rows = try!(stmt.query(&[&self.id])); - Ok(rows.iter().map(|r| { - (Model::from_row(&r), r.get("crate_name")) - }).collect()) + Ok(rows.iter() + .map(|r| (Model::from_row(&r), r.get("crate_name"))) + .collect()) } pub fn authors(&self, conn: &GenericConnection) -> CargoResult> { let stmt = try!(conn.prepare("SELECT * FROM version_authors WHERE version_id = $1")); let rows = try!(stmt.query(&[&self.id])); - rows.into_iter().map(|row| { - let user_id: Option = row.get("user_id"); - let name: String = row.get("name"); - Ok(match user_id { - Some(id) => Author::User(try!(User::find(conn, id))), - None => Author::Name(name), + rows.into_iter() + .map(|row| { + let user_id: Option = row.get("user_id"); + let name: String = row.get("name"); + Ok(match user_id { + Some(id) => Author::User(try!(User::find(conn, id))), + None => Author::Name(name), + }) }) - }).collect() + .collect() } - pub fn add_author(&self, - conn: &GenericConnection, - name: &str) -> CargoResult<()> { + pub fn add_author(&self, conn: &GenericConnection, name: &str) -> CargoResult<()> { println!("add author: {}", name); // TODO: at least try to link `name` to a pre-existing user try!(conn.execute("INSERT INTO version_authors (version_id, name) - VALUES ($1, $2)", &[&self.id, &name])); + VALUES ($1, $2)", + &[&self.id, &name])); Ok(()) } @@ -200,9 +200,8 @@ 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"), @@ -214,7 +213,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. @@ -222,15 +223,11 @@ pub fn index(req: &mut Request) -> CargoResult { let conn = try!(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 // @@ -251,7 +248,9 @@ pub fn index(req: &mut Request) -> CargoResult { } #[derive(RustcEncodable)] - struct R { versions: Vec } + struct R { + versions: Vec, + } Ok(req.json(&R { versions: versions })) } @@ -270,22 +269,24 @@ 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(req: &mut Request) -> CargoResult<(Version, Crate)> { let crate_name = &req.params()["crate_id"]; let semver = &req.params()["version"]; - let semver = try!(semver::Version::parse(semver).map_err(|_| { - human(format!("invalid semver: {}", semver)) - })); + let semver = try!(semver::Version::parse(semver) + .map_err(|_| human(format!("invalid semver: {}", semver)))); let tx = try!(req.tx()); let krate = try!(Crate::find_by_name(tx, crate_name)); let version = try!(Version::find_by_num(tx, krate.id, &semver)); let version = try!(version.chain_error(|| { human(format!("crate `{}` does not have a version `{}`", - crate_name, semver)) + crate_name, + semver)) })); Ok((version, krate)) } @@ -295,13 +296,15 @@ pub fn dependencies(req: &mut Request) -> CargoResult { let (version, _) = try!(version_and_crate(req)); let tx = try!(req.tx()); let deps = try!(version.dependencies(tx)); - 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. @@ -320,8 +323,10 @@ pub fn downloads(req: &mut Request) -> CargoResult { } #[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. @@ -337,10 +342,18 @@ pub fn authors(req: &mut Request) -> CargoResult { } #[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: users, meta: Meta { names: names } })) + struct Meta { + names: Vec, + } + Ok(req.json(&R { + users: users, + meta: Meta { names: names }, + })) } /// Handles the `DELETE /crates/:crate_id/:version/yank` route. @@ -359,7 +372,7 @@ fn modify_yank(req: &mut Request, yanked: bool) -> CargoResult { let tx = try!(req.tx()); let owners = try!(krate.owners(tx)); if try!(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 { @@ -368,6 +381,8 @@ fn modify_yank(req: &mut Request, yanked: bool) -> CargoResult { } #[derive(RustcEncodable)] - struct R { ok: bool } - Ok(req.json(&R{ ok: true })) + struct R { + ok: bool, + } + Ok(req.json(&R { ok: true })) }