flag_locked: bool,
#[serde(rename = "flag_Z")]
flag_z: Vec<String>,
+ flag_registry: Option<String>,
}
pub const USAGE: &'static str = "
--frozen Require Cargo.lock and cache are up to date
--locked Require Cargo.lock is up to date
-Z FLAG ... Unstable (nightly-only) flags to Cargo
+ --registry REGISTRY Registry to use
";
let token = match options.arg_token {
Some(token) => token,
None => {
- let host = match options.flag_host {
- Some(ref host) => host.clone(),
+ let host = match options.flag_registry {
+ Some(ref registry) => {
+ config.get_registry_index(registry)?
+ }
None => {
let src = SourceId::crates_io(config)?;
let mut src = RegistrySource::remote(&src, config);
src.update()?;
- src.config()?.unwrap().api.unwrap()
+ let config = src.config()?.unwrap();
+ options.flag_host.clone().unwrap_or(config.api.unwrap())
}
};
println!("please visit {}me and paste the API Token below", host);
}
};
- ops::registry_login(config, token, options.flag_host)?;
+ ops::registry_login(config, token, options.flag_registry)?;
Ok(())
}
flag_locked: bool,
#[serde(rename = "flag_Z")]
flag_z: Vec<String>,
+ flag_registry: Option<String>,
}
pub const USAGE: &'static str = "
--frozen Require Cargo.lock and cache are up to date
--locked Require Cargo.lock is up to date
-Z FLAG ... Unstable (nightly-only) flags to Cargo
+ --registry REGISTRY Registry to use
This command will modify the owners for a package on the specified registry (or
default). Note that owners of a package can upload new versions, yank old
to_add: options.flag_add,
to_remove: options.flag_remove,
list: options.flag_list,
+ registry: options.flag_registry,
};
ops::modify_owners(config, &opts)?;
Ok(())
flag_locked: bool,
#[serde(rename = "flag_Z")]
flag_z: Vec<String>,
+ flag_registry: Option<String>,
}
pub const USAGE: &'static str = "
--frozen Require Cargo.lock and cache are up to date
--locked Require Cargo.lock is up to date
-Z FLAG ... Unstable (nightly-only) flags to Cargo
+ --registry REGISTRY Registry to publish to
";
flag_jobs: jobs,
flag_dry_run: dry_run,
flag_target: target,
+ flag_registry: registry,
..
} = options;
target: target.as_ref().map(|t| &t[..]),
jobs: jobs,
dry_run: dry_run,
+ registry: registry,
})?;
Ok(())
}
arg_query: Vec<String>,
#[serde(rename = "flag_Z")]
flag_z: Vec<String>,
+ flag_registry: Option<String>,
}
pub const USAGE: &'static str = "
--frozen Require Cargo.lock and cache are up to date
--locked Require Cargo.lock is up to date
-Z FLAG ... Unstable (nightly-only) flags to Cargo
+ --registry REGISTRY Registry to use
";
pub fn execute(options: Options, config: &mut Config) -> CliResult {
flag_host: host, // TODO: Depricated, remove
flag_limit: limit,
arg_query: query,
+ flag_registry: registry,
..
} = options;
host
};
- ops::search(&query.join("+"), config, index, cmp::min(100, limit.unwrap_or(10)) as u8)?;
+ ops::search(&query.join("+"), config, index, cmp::min(100, limit.unwrap_or(10)) as u8, registry)?;
Ok(())
}
flag_locked: bool,
#[serde(rename = "flag_Z")]
flag_z: Vec<String>,
+ flag_registry: Option<String>,
}
pub static USAGE: &'static str = "
--frozen Require Cargo.lock and cache are up to date
--locked Require Cargo.lock is up to date
-Z FLAG ... Unstable (nightly-only) flags to Cargo
+ --registry REGISTRY Registry to use
The yank command removes a previously pushed crate's version from the server's
index. This command does not delete any data, and the crate will still be
options.flag_vers,
options.flag_token,
options.flag_index,
- options.flag_undo)?;
+ options.flag_undo,
+ options.flag_registry)?;
Ok(())
}
}
pub fn alt_registry(config: &Config, key: &str) -> CargoResult<SourceId> {
- if let Some(index) = config.get_string(&format!("registries.{}.index", key))? {
- let url = index.val.to_url()?;
- Ok(SourceId {
- inner: Arc::new(SourceIdInner {
- kind: Kind::Registry,
- canonical_url: git::canonicalize_url(&url)?,
- url: url,
- precise: None,
- }),
- })
- } else { Err(format!("No index found for registry: `{}`", key).into()) }
+ let index = config.get_registry_index(key)?;
+ let url = index.to_url()?;
+ Ok(SourceId {
+ inner: Arc::new(SourceIdInner {
+ kind: Kind::Registry,
+ canonical_url: git::canonicalize_url(&url)?,
+ url: url,
+ precise: None,
+ }),
+ })
}
/// Get this source URL
use core::manifest::ManifestMetadata;
use ops;
use sources::{RegistrySource};
-use util::config::{self, Config, Value, Definition};
+use util::config::{self, Config, ConfigValue};
use util::paths;
use util::ToUrl;
use util::errors::{CargoError, CargoResult, CargoResultExt};
pub jobs: Option<u32>,
pub target: Option<&'cfg str>,
pub dry_run: bool,
+ pub registry: Option<String>,
}
pub fn publish(ws: &Workspace, opts: &PublishOpts) -> CargoResult<()> {
let (mut registry, reg_id) = registry(opts.config,
opts.token.clone(),
- opts.index.clone())?;
+ opts.index.clone(),
+ opts.registry.clone())?;
verify_dependencies(pkg, ®_id)?;
// Prepare a tarball, with a non-surpressable warning if metadata
}
pub fn registry_configuration(config: &Config,
- host: Option<String>) -> CargoResult<RegistryConfig> {
- let (index, token) = match host {
- Some(host) => {
- (Some(Value { val: host.clone(), definition: Definition::Environment }),
- config.get_string(&format!("registry.{}.token", host))?)
+ registry: Option<String>) -> CargoResult<RegistryConfig> {
+
+ let (index, token) = match registry {
+ Some(registry) => {
+ let index = Some(config.get_registry_index(®istry)?);
+ let table = config.get_table(&format!("registry.{}", registry))?.map(|t| t.val);
+ let token = table.and_then(|table| {
+ match table.get("token".into()) {
+ Some(&ConfigValue::String(ref i, _)) => Some(i.to_string()),
+ _ => None,
+ }
+ });
+
+ (index, token)
}
None => {
// Checking out for default index and token
- (config.get_string("registry.index")?,
- config.get_string("registry.token")?)
+ (config.get_string("registry.index")?.map(|p| p.val),
+ config.get_string("registry.token")?.map(|p| p.val))
}
};
Ok(RegistryConfig {
- index: index.map(|p| p.val),
- token: token.map(|p| p.val)
+ index: index,
+ token: token
})
}
pub fn registry(config: &Config,
token: Option<String>,
- index: Option<String>) -> CargoResult<(Registry, SourceId)> {
+ index: Option<String>,
+ registry: Option<String>) -> CargoResult<(Registry, SourceId)> {
// Parse all configuration options
let RegistryConfig {
token: token_config,
- index: _index_config,
- } = registry_configuration(config, index.clone())?;
+ index: index_config,
+ } = registry_configuration(config, registry.clone())?;
let token = token.or(token_config);
- let sid = match index {
- Some(index) => SourceId::for_registry(&index.to_url()?)?,
- None => SourceId::crates_io(config)?,
+ let sid = match (index_config, index) {
+ (Some(index), _) | (None, Some(index)) => SourceId::for_registry(&index.to_url()?)?,
+ (None, None) => SourceId::crates_io(config)?,
};
let api_host = {
let mut src = RegistrySource::remote(&sid, config);
pub fn registry_login(config: &Config,
token: String,
- host: Option<String>) -> CargoResult<()> {
+ registry: Option<String>) -> CargoResult<()> {
let RegistryConfig {
token: old_token,
..
- } = registry_configuration(config, host.clone())?;
+ } = registry_configuration(config, registry.clone())?;
if let Some(old_token) = old_token {
if old_token == token {
}
}
- config::save_credentials(config, token, host)
+ config::save_credentials(config, token, registry)
}
pub struct OwnersOptions {
pub to_add: Option<Vec<String>>,
pub to_remove: Option<Vec<String>>,
pub list: bool,
+ pub registry: Option<String>,
}
pub fn modify_owners(config: &Config, opts: &OwnersOptions) -> CargoResult<()> {
}
};
- let (mut registry, _) = registry(config, opts.token.clone(),
- opts.index.clone())?;
+ let (mut registry, _) = registry(config,
+ opts.token.clone(),
+ opts.index.clone(),
+ opts.registry.clone())?;
if let Some(ref v) = opts.to_add {
let v = v.iter().map(|s| &s[..]).collect::<Vec<_>>();
version: Option<String>,
token: Option<String>,
index: Option<String>,
- undo: bool) -> CargoResult<()> {
+ undo: bool,
+ reg: Option<String>) -> CargoResult<()> {
let name = match krate {
Some(name) => name,
None => {
None => bail!("a version must be specified to yank")
};
- let (mut registry, _) = registry(config, token, index)?;
+ let (mut registry, _) = registry(config, token, index, reg)?;
if undo {
config.shell().status("Unyank", format!("{}:{}", name, version))?;
pub fn search(query: &str,
config: &Config,
index: Option<String>,
- limit: u8) -> CargoResult<()> {
+ limit: u8,
+ reg: Option<String>) -> CargoResult<()> {
fn truncate_with_ellipsis(s: &str, max_length: usize) -> String {
if s.len() < max_length {
s.to_string()
}
}
- let (mut registry, _) = registry(config, None, index)?;
+ let (mut registry, _) = registry(config, None, index, reg)?;
let (crates, total_crates) = registry.search(query, limit).map_err(|e| {
CargoError::from(format!("failed to retrieve search results from the registry: {}", e))
})?;
}
}
+ /// Gets the index for a registry.
+ pub fn get_registry_index(&self, registry: &str) -> CargoResult<String> {
+ Ok(match self.get_string(&format!("registries.{}.index", registry))? {
+ Some(index) => index.val,
+ None => return Err(CargoError::from(format!("No index found for registry: `{}`", registry)).into()),
+ })
+ }
+
/// Loads credentials config from the credentials file into the ConfigValue object, if present.
fn load_credentials(&self, cfg: &mut ConfigValue) -> CargoResult<()> {
let home_path = self.home_path.clone().into_path_unlocked();
pub fn save_credentials(cfg: &Config,
token: String,
- host: Option<String>) -> CargoResult<()> {
+ registry: Option<String>) -> CargoResult<()> {
let mut file = {
cfg.home_path.create_dir()?;
cfg.home_path.open_rw(Path::new("credentials"), cfg,
let key = "token".to_string();
let value = ConfigValue::String(token, file.path().to_path_buf());
- if let Some(host) = host {
+ if let Some(registry) = registry {
let mut map = HashMap::new();
map.insert(key, value);
- (host, CV::Table(map, file.path().to_path_buf()))
+ (registry, CV::Table(map, file.path().to_path_buf()))
} else {
(key, value)
}
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs"))
}
+
+#[test]
+fn block_publish_due_to_no_token() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ // Setup the registry by publishing a package
+ Package::new("bar", "0.0.1").alternative(true).publish();
+
+ // Now perform the actual publish
+ assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
+ .arg("--registry").arg("alternative"),
+ execs().with_status(101));
+}
+
+#[test]
+fn publish_to_alt_registry() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ // Setup the registry by publishing a package
+ Package::new("bar", "0.0.1").alternative(true).publish();
+
+ // Login so that we have the token available
+ assert_that(p.cargo("login")
+ .arg("--registry").arg("alternative").arg("TOKEN"),
+ execs().with_status(0));
+
+ // Now perform the actual publish
+ assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
+ .arg("--registry").arg("alternative"),
+ execs().with_status(0));
+}
use hamcrest::{assert_that, existing_file, is_not};
const TOKEN: &str = "test-token";
+const ORIGINAL_TOKEN: &str = "api-token";
const CONFIG_FILE: &str = r#"
[registry]
token = "api-token"
+
+ [registries.test-reg]
+ index = "dummy_index"
+
+ [registries.test.reg]
+ index = "dummy_index"
"#;
fn setup_old_credentials() {
let config = cargo_home().join("credentials");
t!(fs::create_dir_all(config.parent().unwrap()));
t!(t!(File::create(&config)).write_all(format!(r#"
- token = "api-token"
-
- ["{registry}"]
- token = "api-token"
- "#, registry = registry().to_string())
+ token = "{token}"
+ "#, token = ORIGINAL_TOKEN)
.as_bytes()));
}
-fn check_host_token(mut toml: toml::Value, host_key: &str) -> bool {
- for &key in [host_key, "token"].into_iter() {
- if key.is_empty() {
- continue
- }
+fn check_token(expected_token: &str, registry: Option<&str>) -> bool {
+
+ let credentials = cargo_home().join("credentials");
+ assert_that(&credentials, existing_file());
- match toml {
- toml::Value::Table(table) => {
- if let Some(v) = table.get(key) {
- toml = v.clone();
- } else {
- return false;
+ let mut contents = String::new();
+ File::open(&credentials).unwrap().read_to_string(&mut contents).unwrap();
+ let toml: toml::Value = contents.parse().unwrap();
+
+ let token = match (registry, toml) {
+ // A registry has been provided, so check that the token exists in a
+ // table for the registry.
+ (Some(registry), toml::Value::Table(table)) => {
+ table.get(registry).and_then(|registry_table| {
+ match registry_table.get("token") {
+ Some(&toml::Value::String(ref token)) => Some(token.as_str().to_string()),
+ _ => None,
+ }
+ })
+ },
+ // There is no registry provided, so check the global token instead.
+ (None, toml::Value::Table(table)) => {
+ table.get("token").and_then(|v| {
+ match v {
+ &toml::Value::String(ref token) => Some(token.as_str().to_string()),
+ _ => None,
}
- }
- _ => break,
+ })
}
- }
+ _ => None
+ };
- match toml {
- toml::Value::String(token) => (&token == TOKEN),
- _ => false,
+ if let Some(token_val) = token {
+ token_val == expected_token
+ } else {
+ false
}
}
File::open(&config).unwrap().read_to_string(&mut contents).unwrap();
assert_eq!(CONFIG_FILE, contents);
- let credentials = cargo_home().join("credentials");
- assert_that(&credentials, existing_file());
-
- contents.clear();
- File::open(&credentials).unwrap().read_to_string(&mut contents).unwrap();
- assert!(check_host_token(contents.parse().unwrap(), ®istry().to_string()));
+ // Ensure that we get the new token for the registry
+ assert!(check_token(TOKEN, None));
}
#[test]
let config = cargo_home().join("config");
assert_that(&config, is_not(existing_file()));
- let credentials = cargo_home().join("credentials");
- assert_that(&credentials, existing_file());
-
- let mut contents = String::new();
- File::open(&credentials).unwrap().read_to_string(&mut contents).unwrap();
- assert!(check_host_token(contents.parse().unwrap(), ®istry().to_string()));
+ // Ensure that we get the new token for the registry
+ assert!(check_token(TOKEN, None));
}
#[test]
assert_that(cargo_process().arg("login")
.arg("--host").arg(registry().to_string()).arg(TOKEN),
execs().with_status(0));
- assert_that(cargo_process().arg("login").arg(TOKEN),
- execs().with_status(0));
let config = cargo_home().join("config");
assert_that(&config, is_not(existing_file()));
- let credentials = cargo_home().join("credentials");
- assert_that(&credentials, existing_file());
-
- let mut contents = String::new();
- File::open(&credentials).unwrap().read_to_string(&mut contents).unwrap();
- let toml: toml::Value = contents.parse().unwrap();
- assert!(check_host_token(toml.clone(), ®istry().to_string()));
- assert!(check_host_token(toml, ""));
+ // Ensure that we get the new token for the registry
+ assert!(check_token(TOKEN, None));
}
#[test]
setup_old_credentials();
setup_new_credentials();
- assert_that(cargo_process().arg("login").arg(TOKEN),
- execs().with_status(0));
-
assert_that(cargo_process().arg("login")
.arg("--host").arg(registry().to_string()).arg(TOKEN),
execs().with_status(0));
let token = config.get_string("registry.token").unwrap().map(|p| p.val);
assert_eq!(token.unwrap(), TOKEN);
+}
+
+#[test]
+fn registry_credentials() {
+ setup_old_credentials();
+ setup_new_credentials();
+
+ let reg = "test-reg";
+
+ assert_that(cargo_process().arg("login")
+ .arg("--registry").arg(reg).arg(TOKEN),
+ execs().with_status(0));
+
+ // Ensure that we have not updated the default token
+ assert!(check_token(ORIGINAL_TOKEN, None));
+
+ // Also ensure that we get the new token for the registry
+ assert!(check_token(TOKEN, Some(reg)));
+}
+
+#[test]
+fn registry_credentials_with_dots() {
+ setup_old_credentials();
+ setup_new_credentials();
+
+ let reg = "test.reg";
+
+ assert_that(cargo_process().arg("login")
+ .arg("--registry").arg(reg).arg(TOKEN),
+ execs().with_status(0));
+
+ // Ensure that we have not updated the default token
+ assert!(check_token(ORIGINAL_TOKEN, None));
- let token_host = config.get_string(&format!(r#"registry.{}.token"#, registry().to_string()))
- .unwrap().map(|p| p.val);
- assert_eq!(token_host.unwrap(), TOKEN);
+ // Also ensure that we get the new token for the registry
+ assert!(check_token(TOKEN, Some(reg)));
}