diff --git a/crates/crates-io/lib.rs b/crates/crates-io/lib.rs index becd02af8..bd85e8697 100644 --- a/crates/crates-io/lib.rs +++ b/crates/crates-io/lib.rs @@ -149,15 +149,41 @@ impl Registry { pub fn add_owners(&mut self, krate: &str, owners: &[&str]) -> Result { let body = serde_json::to_string(&OwnersReq { users: owners })?; let body = self.put(&format!("/crates/{}/owners", krate), body.as_bytes())?; - assert!(serde_json::from_str::(&body)?.ok); - Ok(serde_json::from_str::(&body)?.msg) + let body = if body.is_empty() { + r#"{"ok":false,"msg":"response body is empty"}"#.parse()? + } else { + body + }; + match serde_json::from_str::(&body) { + Ok(response) => { + if response.ok { + Ok(response.msg) + } else { + bail!("{}", response.msg) + } + } + _ => bail!("failed to parse response body"), + } } - pub fn remove_owners(&mut self, krate: &str, owners: &[&str]) -> Result<()> { + pub fn remove_owners(&mut self, krate: &str, owners: &[&str]) -> Result { let body = serde_json::to_string(&OwnersReq { users: owners })?; let body = self.delete(&format!("/crates/{}/owners", krate), Some(body.as_bytes()))?; - assert!(serde_json::from_str::(&body)?.ok); - Ok(()) + let body = if body.is_empty() { + r#"{"ok":false,"msg":"response body is empty"}"#.parse()? + } else { + body + }; + match serde_json::from_str::(&body) { + Ok(response) => { + if response.ok { + Ok(response.msg) + } else { + bail!("{}", response.msg) + } + } + _ => bail!("failed to parse response body"), + } } pub fn list_owners(&mut self, krate: &str) -> Result> { diff --git a/src/doc/src/reference/registries.md b/src/doc/src/reference/registries.md index 9eaf52358..184ede117 100644 --- a/src/doc/src/reference/registries.md +++ b/src/doc/src/reference/registries.md @@ -546,7 +546,9 @@ A successful response includes the JSON object: ```javascript { // Indicates the remove succeeded, always true. - "ok": true + "ok": true, + // A string to be displayed to the user. + "msg": "user someone has been deleted from owners of crate cargo" } ``` diff --git a/tests/testsuite/owner.rs b/tests/testsuite/owner.rs index 0a7e7154b..d37206b20 100644 --- a/tests/testsuite/owner.rs +++ b/tests/testsuite/owner.rs @@ -6,12 +6,21 @@ use cargo_test_support::paths::CargoPathExt; use cargo_test_support::project; use cargo_test_support::registry::{self, api_path, registry_url}; -fn setup(name: &str) { +fn setup(name: &str, content: Option<&str>) { let dir = api_path().join(format!("api/v1/crates/{}", name)); dir.mkdir_p(); - fs::write( - dir.join("owners"), - r#"{ + match content { + Some(body) => { + fs::write(dir.join("owners"), body).unwrap(); + } + None => {} + } +} + +#[cargo_test] +fn simple_list() { + registry::init(); + let content = r#"{ "users": [ { "id": 70, @@ -19,15 +28,8 @@ fn setup(name: &str) { "name": "Core" } ] - }"#, - ) - .unwrap(); -} - -#[cargo_test] -fn simple_list() { - registry::init(); - setup("foo"); + }"#; + setup("foo", Some(content)); let p = project() .file( @@ -48,3 +50,67 @@ fn simple_list() { .arg(registry_url().to_string()) .run(); } + +#[cargo_test] +fn simple_add() { + registry::init(); + setup("foo", None); + + let p = project() + .file( + "Cargo.toml", + r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("owner -a username --index") + .arg(registry_url().to_string()) + .with_status(101) + .with_stderr( + " Updating `[..]` index +error: failed to invite owners to crate foo: response body is empty", + ) + .run(); +} + +#[cargo_test] +fn simple_remove() { + registry::init(); + setup("foo", None); + + let p = project() + .file( + "Cargo.toml", + r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("owner -r username --index") + .arg(registry_url().to_string()) + .with_status(101) + .with_stderr( + " Updating `[..]` index + Owner removing [\"username\"] from crate foo +error: failed to remove owners from crate foo + +Caused by: + response body is empty", + ) + .run(); +}