blob: e523737340f6713465f1290b864d45abf487b005 [file] [log] [blame]
//! Interacts with the registry [login API][1].
//!
//! This doesn't really call any web API at this moment. Instead, it's just an
//! operation for `cargo login`.
//!
//! [1]: https://doc.rust-lang.org/nightly/cargo/reference/registry-web-api.html#login
use std::io::IsTerminal;
use crate::util::auth;
use crate::util::auth::AuthorizationError;
use crate::CargoResult;
use crate::Config;
use cargo_credential::LoginOptions;
use cargo_credential::Secret;
use super::get_source_id;
use super::registry;
pub fn registry_login(
config: &Config,
token_from_cmdline: Option<Secret<&str>>,
reg: Option<&str>,
args: &[&str],
) -> CargoResult<()> {
let source_ids = get_source_id(config, None, reg)?;
let login_url = match registry(config, token_from_cmdline.clone(), None, reg, false, None) {
Ok((registry, _)) => Some(format!("{}/me", registry.host())),
Err(e) if e.is::<AuthorizationError>() => e
.downcast::<AuthorizationError>()
.unwrap()
.login_url
.map(|u| u.to_string()),
Err(e) => return Err(e),
};
let mut token_from_stdin = None;
let token = token_from_cmdline.or_else(|| {
if !std::io::stdin().is_terminal() {
let token = std::io::read_to_string(std::io::stdin()).unwrap_or_default();
if !token.is_empty() {
token_from_stdin = Some(token);
}
}
token_from_stdin.as_deref().map(Secret::from)
});
let options = LoginOptions {
token,
login_url: login_url.as_deref(),
};
auth::login(config, &source_ids.original, options, args)?;
Ok(())
}