Skip to content

Commit d2736a0

Browse files
committed
Return warnings about invalid categories
1 parent bf98e94 commit d2736a0

File tree

7 files changed

+108
-12
lines changed

7 files changed

+108
-12
lines changed

src/category.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,23 @@ impl Category {
6363

6464
pub fn update_crate(conn: &GenericConnection,
6565
krate: &Crate,
66-
categories: &[String]) -> CargoResult<()> {
66+
categories: &[String]) -> CargoResult<Vec<String>> {
6767
let old_categories = try!(krate.categories(conn));
6868
let old_categories_ids: HashSet<_> = old_categories.iter().map(|cat| {
6969
cat.id
7070
}).collect();
7171

7272
// If a new category specified is not in the database, filter
73-
// it out and don't add it.
73+
// it out and don't add it. Return it to be able to warn about it.
74+
let mut invalid_categories = vec![];
7475
let new_categories: Vec<Category> = categories.iter().flat_map(|c| {
75-
Category::find_by_slug(conn, &c).ok()
76+
match Category::find_by_slug(conn, &c) {
77+
Ok(cat) => Some(cat),
78+
Err(_) => {
79+
invalid_categories.push(c.to_string());
80+
None
81+
},
82+
}
7683
}).collect();
7784

7885
let new_categories_ids: HashSet<_> = new_categories.iter().map(|cat| {
@@ -106,7 +113,7 @@ impl Category {
106113
&[]));
107114
}
108115

109-
Ok(())
116+
Ok(invalid_categories)
110117
}
111118
}
112119

src/krate.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -739,8 +739,16 @@ pub fn new(req: &mut Request) -> CargoResult<Response> {
739739
// Update all keywords for this crate
740740
try!(Keyword::update_crate(try!(req.tx()), &krate, &keywords));
741741

742-
// Update all categories for this crate
743-
try!(Category::update_crate(try!(req.tx()), &krate, &categories));
742+
// Update all categories for this crate, collecting any invalid categories
743+
// in order to be able to warn about them
744+
let ignored_invalid_categories = try!(
745+
Category::update_crate(try!(req.tx()), &krate, &categories)
746+
);
747+
let warnings: Vec<String> =
748+
ignored_invalid_categories.iter().map(|category| {
749+
format!("'{}' is not a recognized category name \
750+
and has been ignored.", category)
751+
}).collect();
744752

745753
// Upload the crate to S3
746754
let mut handle = req.app().handle();
@@ -797,8 +805,8 @@ pub fn new(req: &mut Request) -> CargoResult<Response> {
797805
bomb.path = None;
798806

799807
#[derive(RustcEncodable)]
800-
struct R { krate: EncodableCrate }
801-
Ok(req.json(&R { krate: krate.minimal_encodable() }))
808+
struct R { krate: EncodableCrate, warnings: Vec<String> }
809+
Ok(req.json(&R { krate: krate.minimal_encodable(), warnings: warnings }))
802810
}
803811

804812
fn parse_new_headers(req: &mut Request) -> CargoResult<(upload::NewCrate, User)> {

src/tests/all.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,13 @@ fn new_req_with_keywords(app: Arc<App>, krate: Crate, version: &str,
283283
return req;
284284
}
285285

286+
fn new_req_with_categories(app: Arc<App>, krate: Crate, version: &str,
287+
cats: Vec<String>) -> MockRequest {
288+
let mut req = ::req(app, Method::Put, "/api/v1/crates/new");
289+
req.with_body(&new_req_body(krate, version, Vec::new(), Vec::new(), cats));
290+
return req;
291+
}
292+
286293
fn new_req_body_foo_version_2() -> Vec<u8> {
287294
new_req_body(::krate("foo"), "2.0.0", Vec::new(), Vec::new(), Vec::new())
288295
}

src/tests/category.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,11 @@ fn update_crate() {
9494
assert_eq!(cnt(&mut req, "category-2"), 0);
9595

9696
// Attempting to add one valid category and one invalid category
97-
Category::update_crate(tx(&req), &krate, &["cat1".to_string(),
98-
"catnope".to_string()]).unwrap();
99-
97+
let invalid_crates = Category::update_crate(
98+
tx(&req), &krate, &["cat1".to_string(),
99+
"catnope".to_string()]
100+
).unwrap();
101+
assert_eq!(invalid_crates, vec!["catnope".to_string()]);
100102
assert_eq!(cnt(&mut req, "cat1"), 1);
101103
assert_eq!(cnt(&mut req, "category-2"), 0);
102104

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
===REQUEST 331
2+
PUT http://alexcrichton-test.s3.amazonaws.com/crates/foo/foo-1.0.0.crate HTTP/1.1
3+
Accept: */*
4+
Proxy-Connection: Keep-Alive
5+
Authorization: AWS AKIAJF3GEK7N44BACDZA:GDxGb6r3SIqo9wXuzHrgMNWekwk=
6+
Content-Length: 0
7+
Host: alexcrichton-test.s3.amazonaws.com
8+
Content-Type: application/x-tar
9+
Date: Sun, 28 Jun 2015 14:07:17 -0700
10+
11+
12+
===RESPONSE 258
13+
HTTP/1.1 200
14+
x-amz-request-id: CB0E925D8E3AB3E8
15+
x-amz-id-2: SiaMwszM1p2TzXlLauvZ6kRKcUCg7HoyBW29vts42w9ArrLwkJWl8vuvPuGFkpM6XGH+YXN852g=
16+
date: Sun, 28 Jun 2015 21:07:51 GMT
17+
etag: "d41d8cd98f00b204e9800998ecf8427e"
18+
content-length: 0
19+
server: AmazonS3
20+
21+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
===REQUEST 331
2+
PUT http://alexcrichton-test.s3.amazonaws.com/crates/foo/foo-1.0.0.crate HTTP/1.1
3+
Accept: */*
4+
Proxy-Connection: Keep-Alive
5+
Authorization: AWS AKIAJF3GEK7N44BACDZA:GDxGb6r3SIqo9wXuzHrgMNWekwk=
6+
Content-Length: 0
7+
Host: alexcrichton-test.s3.amazonaws.com
8+
Content-Type: application/x-tar
9+
Date: Sun, 28 Jun 2015 14:07:17 -0700
10+
11+
12+
===RESPONSE 258
13+
HTTP/1.1 200
14+
x-amz-request-id: CB0E925D8E3AB3E8
15+
x-amz-id-2: SiaMwszM1p2TzXlLauvZ6kRKcUCg7HoyBW29vts42w9ArrLwkJWl8vuvPuGFkpM6XGH+YXN852g=
16+
date: Sun, 28 Jun 2015 21:07:51 GMT
17+
etag: "d41d8cd98f00b204e9800998ecf8427e"
18+
content-length: 0
19+
server: AmazonS3
20+
21+

src/tests/krate.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ struct CrateMeta { total: i32 }
2626
#[derive(RustcDecodable)]
2727
struct GitCrate { name: String, vers: String, deps: Vec<String>, cksum: String }
2828
#[derive(RustcDecodable)]
29-
struct GoodCrate { krate: EncodableCrate }
29+
struct GoodCrate { krate: EncodableCrate, warnings: Vec<String> }
3030
#[derive(RustcDecodable)]
3131
struct CrateResponse { krate: EncodableCrate, versions: Vec<EncodableVersion>, keywords: Vec<EncodableKeyword> }
3232
#[derive(RustcDecodable)]
@@ -884,6 +884,36 @@ fn bad_keywords() {
884884
}
885885
}
886886

887+
#[test]
888+
fn good_categories() {
889+
let (_b, app, middle) = ::app();
890+
let krate = ::krate("foo");
891+
let cats = vec!["cat1".into()];
892+
let mut req = ::new_req_with_categories(app, krate, "1.0.0", cats);
893+
::mock_category(&mut req, "cat1", "cat1");
894+
::mock_user(&mut req, ::user("foo"));
895+
let mut response = ok_resp!(middle.call(&mut req));
896+
let json: GoodCrate = ::json(&mut response);
897+
assert_eq!(json.krate.name, "foo");
898+
assert_eq!(json.krate.max_version, "1.0.0");
899+
assert_eq!(json.warnings.len(), 0);
900+
}
901+
902+
#[test]
903+
fn ignored_categories() {
904+
let (_b, app, middle) = ::app();
905+
let krate = ::krate("foo");
906+
let cats = vec!["bar".into()];
907+
let mut req = ::new_req_with_categories(app, krate, "1.0.0", cats);
908+
::mock_user(&mut req, ::user("foo"));
909+
let mut response = ok_resp!(middle.call(&mut req));
910+
let json: GoodCrate = ::json(&mut response);
911+
assert_eq!(json.krate.name, "foo");
912+
assert_eq!(json.krate.max_version, "1.0.0");
913+
assert_eq!(json.warnings, vec!["\'bar\' is not a recognized category name \
914+
and has been ignored.".to_string()]);
915+
}
916+
887917
#[test]
888918
fn reverse_dependencies() {
889919
let (_b, app, middle) = ::app();

0 commit comments

Comments
 (0)