cargo/ops/registry/
owner.rs

1//! Interacts with the registry [owners API][1].
2//!
3//! [1]: https://doc.rust-lang.org/nightly/cargo/reference/registry-web-api.html#owners
4
5use anyhow::Context as _;
6use cargo_credential::Operation;
7use cargo_credential::Secret;
8
9use crate::core::Workspace;
10use crate::drop_print;
11use crate::drop_println;
12use crate::util::important_paths::find_root_manifest_for_wd;
13use crate::CargoResult;
14use crate::GlobalContext;
15
16use super::RegistryOrIndex;
17
18pub struct OwnersOptions {
19    pub krate: Option<String>,
20    pub token: Option<Secret<String>>,
21    pub reg_or_index: Option<RegistryOrIndex>,
22    pub to_add: Option<Vec<String>>,
23    pub to_remove: Option<Vec<String>>,
24    pub list: bool,
25}
26
27pub fn modify_owners(gctx: &GlobalContext, opts: &OwnersOptions) -> CargoResult<()> {
28    let name = match opts.krate {
29        Some(ref name) => name.clone(),
30        None => {
31            let manifest_path = find_root_manifest_for_wd(gctx.cwd())?;
32            let ws = Workspace::new(&manifest_path, gctx)?;
33            ws.current()?.package_id().name().to_string()
34        }
35    };
36
37    let operation = Operation::Owners { name: &name };
38    let source_ids = super::get_source_id(gctx, opts.reg_or_index.as_ref())?;
39    let (mut registry, _) = super::registry(
40        gctx,
41        &source_ids,
42        opts.token.as_ref().map(Secret::as_deref),
43        opts.reg_or_index.as_ref(),
44        true,
45        Some(operation),
46    )?;
47
48    if let Some(ref v) = opts.to_add {
49        let v = v.iter().map(|s| &s[..]).collect::<Vec<_>>();
50        let msg = registry.add_owners(&name, &v).with_context(|| {
51            format!(
52                "failed to invite owners to crate `{}` on registry at {}",
53                name,
54                registry.host()
55            )
56        })?;
57
58        gctx.shell().status("Owner", msg)?;
59    }
60
61    if let Some(ref v) = opts.to_remove {
62        let v = v.iter().map(|s| &s[..]).collect::<Vec<_>>();
63        gctx.shell()
64            .status("Owner", format!("removing {:?} from crate {}", v, name))?;
65        registry.remove_owners(&name, &v).with_context(|| {
66            format!(
67                "failed to remove owners from crate `{}` on registry at {}",
68                name,
69                registry.host()
70            )
71        })?;
72    }
73
74    if opts.list {
75        let owners = registry.list_owners(&name).with_context(|| {
76            format!(
77                "failed to list owners of crate `{}` on registry at {}",
78                name,
79                registry.host()
80            )
81        })?;
82        for owner in owners.iter() {
83            drop_print!(gctx, "{}", owner.login);
84            match (owner.name.as_ref(), owner.email.as_ref()) {
85                (Some(name), Some(email)) => drop_println!(gctx, " ({} <{}>)", name, email),
86                (Some(s), None) | (None, Some(s)) => drop_println!(gctx, " ({})", s),
87                (None, None) => drop_println!(gctx),
88            }
89        }
90    }
91
92    Ok(())
93}