let (index, token) = match registry {
Some(registry) => {
(Some(config.get_registry_index(®istry)?.to_string()),
- config.get_string(&format!("registry.{}.token", registry))?.map(|p| p.val))
+ config.get_string(&format!("registries.{}.token", registry))?.map(|p| p.val))
}
None => {
// Checking out for default index and token
format!("could not parse TOML configuration in `{}`", credentials.display())
})?;
- let value = CV::from_toml(&credentials, toml).chain_err(|| {
+ let mut value = CV::from_toml(&credentials, toml).chain_err(|| {
format!("failed to load TOML configuration from `{}`", credentials.display())
})?;
- let cfg = match *cfg {
- CV::Table(ref mut map, _) => map,
- _ => unreachable!(),
- };
-
- let registry = cfg.entry("registry".into())
- .or_insert_with(|| CV::Table(HashMap::new(), PathBuf::from(".")));
-
- match (registry, value) {
- (&mut CV::Table(ref mut old, _), CV::Table(ref mut new, _)) => {
- // Take ownership of `new` by swapping it with an empty hashmap, so we can move
- // into an iterator.
- let new = mem::replace(new, HashMap::new());
- for (key, value) in new {
- old.insert(key, value);
+ // backwards compatibility for old .cargo/credentials layout
+ {
+ let value = match value {
+ CV::Table(ref mut value, _) => value,
+ _ => unreachable!(),
+ };
+
+ if let Some(token) = value.remove("token") {
+ if let Vacant(entry) = value.entry("registry".into()) {
+ let mut map = HashMap::new();
+ map.insert("token".into(), token);
+ let table = CV::Table(map, PathBuf::from("."));
+ entry.insert(table);
}
}
- _ => unreachable!(),
}
+ // we want value to override cfg, so swap these
+ mem::swap(cfg, &mut value);
+ cfg.merge(value)?;
+
Ok(())
}
let (key, value) = {
let key = "token".to_string();
let value = ConfigValue::String(token, file.path().to_path_buf());
+ let mut map = HashMap::new();
+ map.insert(key, value);
+ let table = CV::Table(map, file.path().to_path_buf());
if let Some(registry) = registry {
let mut map = HashMap::new();
- map.insert(key, value);
- (registry, CV::Table(map, file.path().to_path_buf()))
+ map.insert(registry, table);
+ ("registries".into(), CV::Table(map, file.path().to_path_buf()))
} else {
- (key, value)
+ ("registry".into(), table)
}
};
})?;
let mut toml = cargo_toml::parse(&contents, file.path(), cfg)?;
+
+ // move the old token location to the new one
+ if let Some(token) = toml.as_table_mut().unwrap().remove("token") {
+ let mut map = HashMap::new();
+ map.insert("token".to_string(), token);
+ toml.as_table_mut().unwrap().insert("registry".into(), map.into());
+ }
+
toml.as_table_mut()
.unwrap()
.insert(key, value.into_toml());
t!(fs::create_dir_all(config.parent().unwrap()));
t!(t!(File::create(&config)).write_all(format!(r#"
[registry]
- token = "api-token"
+ token = "api-token"
[registries.alternative]
index = "{registry}"
let credentials = paths::root().join("home/.cargo/credentials");
t!(fs::create_dir_all(credentials.parent().unwrap()));
t!(t!(File::create(&credentials)).write_all(br#"
- [alternative]
+ [registries.alternative]
token = "api-token"
"#));
// 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| {
+ table.get("registries")
+ .and_then(|registries_table| registries_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| {
+ table.get("registry")
+ .and_then(|registry_table| registry_table.get("token"))
+ .and_then(|v| {
match v {
&toml::Value::String(ref token) => Some(token.as_str().to_string()),
_ => None,
extern crate tar;
use std::io::prelude::*;
-use std::fs::File;
+use std::fs::{self, File};
use std::io::SeekFrom;
use cargotest::ChannelChanger;
}
}
+#[test]
+fn old_token_location() {
+ publish::setup();
+
+ // publish::setup puts a token in this file.
+ fs::remove_file(paths::root().join(".cargo/config")).unwrap();
+
+ let credentials = paths::root().join("home/.cargo/credentials");
+ File::create(credentials)
+ .unwrap()
+ .write_all(br#"
+ token = "api-token"
+ "#)
+ .unwrap();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("publish").arg("--no-verify")
+ .arg("--index").arg(publish::registry().to_string()),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] registry `{reg}`
+[WARNING] manifest has no documentation, [..]
+See [..]
+[PACKAGING] foo v0.0.1 ({dir})
+[UPLOADING] foo v0.0.1 ({dir})
+",
+ dir = p.url(),
+ reg = publish::registry())));
+
+ let mut f = File::open(&publish::upload_path().join("api/v1/crates/new")).unwrap();
+ // Skip the metadata payload and the size of the tarball
+ let mut sz = [0; 4];
+ assert_eq!(f.read(&mut sz).unwrap(), 4);
+ let sz = ((sz[0] as u32) << 0) |
+ ((sz[1] as u32) << 8) |
+ ((sz[2] as u32) << 16) |
+ ((sz[3] as u32) << 24);
+ f.seek(SeekFrom::Current(sz as i64 + 4)).unwrap();
+
+ // Verify the tarball
+ let mut rdr = GzDecoder::new(f);
+ assert_eq!(rdr.header().unwrap().filename().unwrap(), b"foo-0.0.1.crate");
+ let mut contents = Vec::new();
+ rdr.read_to_end(&mut contents).unwrap();
+ let mut ar = Archive::new(&contents[..]);
+ for file in ar.entries().unwrap() {
+ let file = file.unwrap();
+ let fname = file.header().path_bytes();
+ let fname = &*fname;
+ assert!(fname == b"foo-0.0.1/Cargo.toml" ||
+ fname == b"foo-0.0.1/Cargo.toml.orig" ||
+ fname == b"foo-0.0.1/src/main.rs",
+ "unexpected filename: {:?}", file.header().path());
+ }
+}
+
// TODO: Deprecated
// remove once it has been decided --host can be removed
#[test]