Skip to content

Commit

Permalink
Merge pull request #374 from houqp/qp_pypi
Browse files Browse the repository at this point in the history
add support for loading pypi cred from token and pypirc
  • Loading branch information
konstin authored Nov 10, 2020
2 parents 274eb3d + d3827f8 commit e5a01c4
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 4 deletions.
91 changes: 91 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,16 @@ toml = "0.5.6"
walkdir = "2.3.1"
zip = "0.5.5"
thiserror = "1.0.20"
dirs = { version = "3.0.1", optional = true }
configparser = { version = "1.0.0", optional = true }

[dev-dependencies]
indoc = "1.0.2"

[features]
default = ["auditwheel", "log", "upload", "rustls", "human-panic"]
auditwheel = []
upload = ["reqwest", "rpassword"]
upload = ["reqwest", "rpassword", "configparser", "dirs"]
password-storage = ["upload", "keyring"]
log = ["pretty_env_logger"]
# We use rustls for manylinux compliance and because unlike both dynamic and
Expand Down
48 changes: 45 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use anyhow::{bail, Context, Result};
#[cfg(feature = "upload")]
use bytesize::ByteSize;
use cargo_metadata::MetadataCommand;
#[cfg(feature = "upload")]
use configparser::ini::Ini;
#[cfg(feature = "human-panic")]
use human_panic::setup_panic;
#[cfg(feature = "password-storage")]
Expand Down Expand Up @@ -70,14 +72,54 @@ fn get_username() -> String {
}

#[cfg(feature = "upload")]
/// Asks for username and password for a registry account where missing.
fn complete_registry(opt: &PublishOpt) -> Result<(Registry, bool)> {
fn load_pypi_cred_from_config(package_name: &str) -> Option<(String, String)> {
if let Some(mut config_path) = dirs::home_dir() {
config_path.push(".pypirc");
if let Ok(pypirc) = fs::read_to_string(config_path.as_path()) {
let mut config = Ini::new();
if config.read(pypirc).is_err() {
return None;
}

if let (Some(username), Some(password)) = (
config.get(package_name, "username"),
config.get(package_name, "password"),
) {
return Some((username, password));
}
}
}

None
}

#[cfg(feature = "upload")]
fn resolve_pypi_cred(opt: &PublishOpt, package_name: &str) -> (String, String, bool) {
// API token from environment variable takes priority
if let Ok(token) = env::var("MATURIN_PYPI_TOKEN") {
return ("__token__".to_string(), token, false);
}

// load creds from pypirc if found
if let Some((username, password)) = load_pypi_cred_from_config(package_name) {
println!("🔐 Using credential in pypirc for upload");
return (username, password, false);
}

// fallback to username and password
let username = opt.username.clone().unwrap_or_else(get_username);
let (password, reenter) = match opt.password {
Some(ref password) => (password.clone(), false),
None => get_password(&username),
};

(username, password, reenter)
}

#[cfg(feature = "upload")]
/// Asks for username and password for a registry account where missing.
fn complete_registry(opt: &PublishOpt, package_name: &str) -> Result<(Registry, bool)> {
let (username, password, reenter) = resolve_pypi_cred(opt, package_name);
let registry = Registry::new(username, password, Url::parse(&opt.registry)?);

Ok((registry, reenter))
Expand Down Expand Up @@ -321,7 +363,7 @@ fn upload_ui(build: BuildOptions, publish: &PublishOpt, no_sdist: bool) -> Resul
}
}

let (mut registry, reenter) = complete_registry(&publish)?;
let (mut registry, reenter) = complete_registry(&publish, &build_context.metadata21.name)?;

loop {
println!("🚀 Uploading {} packages", wheels.len());
Expand Down

0 comments on commit e5a01c4

Please sign in to comment.