Skip to content

Commit 4e618dd

Browse files
committed
Auto merge of #4839 - sfackler:consistent-config, r=withoutboats
Make .cargo/credentials a subset of .cargo/config Previously, .cargo/credentials looked like ```toml token = "..." [my-registry] token = "..." ``` And was simply merged into the `registry` block of .cargo/config. This meant that custom registry tokens were under `registry.my-registry.token` rather than `registries.my-registry.token` which is where the index was located, and that you couldn't have a custom registry named `token` or it'd conflict with the token for the default registry. This commit changes things such that .cargo/credentials has the same layout as .cargo/config, but only contains token values. For backwards compatibility, we move `token` to `registry.token` when parsing.
2 parents 9275e0d + 5cb5e7d commit 4e618dd

File tree

5 files changed

+108
-26
lines changed

5 files changed

+108
-26
lines changed

src/cargo/ops/registry.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ pub fn registry_configuration(config: &Config,
220220
let (index, token) = match registry {
221221
Some(registry) => {
222222
(Some(config.get_registry_index(&registry)?.to_string()),
223-
config.get_string(&format!("registry.{}.token", registry))?.map(|p| p.val))
223+
config.get_string(&format!("registries.{}.token", registry))?.map(|p| p.val))
224224
}
225225
None => {
226226
// Checking out for default index and token

src/cargo/util/config.rs

+32-20
Original file line numberDiff line numberDiff line change
@@ -573,30 +573,31 @@ impl Config {
573573
format!("could not parse TOML configuration in `{}`", credentials.display())
574574
})?;
575575

576-
let value = CV::from_toml(&credentials, toml).chain_err(|| {
576+
let mut value = CV::from_toml(&credentials, toml).chain_err(|| {
577577
format!("failed to load TOML configuration from `{}`", credentials.display())
578578
})?;
579579

580-
let cfg = match *cfg {
581-
CV::Table(ref mut map, _) => map,
582-
_ => unreachable!(),
583-
};
584-
585-
let registry = cfg.entry("registry".into())
586-
.or_insert_with(|| CV::Table(HashMap::new(), PathBuf::from(".")));
587-
588-
match (registry, value) {
589-
(&mut CV::Table(ref mut old, _), CV::Table(ref mut new, _)) => {
590-
// Take ownership of `new` by swapping it with an empty hashmap, so we can move
591-
// into an iterator.
592-
let new = mem::replace(new, HashMap::new());
593-
for (key, value) in new {
594-
old.insert(key, value);
580+
// backwards compatibility for old .cargo/credentials layout
581+
{
582+
let value = match value {
583+
CV::Table(ref mut value, _) => value,
584+
_ => unreachable!(),
585+
};
586+
587+
if let Some(token) = value.remove("token") {
588+
if let Vacant(entry) = value.entry("registry".into()) {
589+
let mut map = HashMap::new();
590+
map.insert("token".into(), token);
591+
let table = CV::Table(map, PathBuf::from("."));
592+
entry.insert(table);
595593
}
596594
}
597-
_ => unreachable!(),
598595
}
599596

597+
// we want value to override cfg, so swap these
598+
mem::swap(cfg, &mut value);
599+
cfg.merge(value)?;
600+
600601
Ok(())
601602
}
602603

@@ -910,13 +911,16 @@ pub fn save_credentials(cfg: &Config,
910911
let (key, value) = {
911912
let key = "token".to_string();
912913
let value = ConfigValue::String(token, file.path().to_path_buf());
914+
let mut map = HashMap::new();
915+
map.insert(key, value);
916+
let table = CV::Table(map, file.path().to_path_buf());
913917

914918
if let Some(registry) = registry {
915919
let mut map = HashMap::new();
916-
map.insert(key, value);
917-
(registry, CV::Table(map, file.path().to_path_buf()))
920+
map.insert(registry, table);
921+
("registries".into(), CV::Table(map, file.path().to_path_buf()))
918922
} else {
919-
(key, value)
923+
("registry".into(), table)
920924
}
921925
};
922926

@@ -926,6 +930,14 @@ pub fn save_credentials(cfg: &Config,
926930
})?;
927931

928932
let mut toml = cargo_toml::parse(&contents, file.path(), cfg)?;
933+
934+
// move the old token location to the new one
935+
if let Some(token) = toml.as_table_mut().unwrap().remove("token") {
936+
let mut map = HashMap::new();
937+
map.insert("token".to_string(), token);
938+
toml.as_table_mut().unwrap().insert("registry".into(), map.into());
939+
}
940+
929941
toml.as_table_mut()
930942
.unwrap()
931943
.insert(key, value.into_toml());

tests/cargotest/support/publish.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub fn setup() -> Repository {
1212
t!(fs::create_dir_all(config.parent().unwrap()));
1313
t!(t!(File::create(&config)).write_all(format!(r#"
1414
[registry]
15-
token = "api-token"
15+
token = "api-token"
1616
1717
[registries.alternative]
1818
index = "{registry}"
@@ -21,7 +21,7 @@ pub fn setup() -> Repository {
2121
let credentials = paths::root().join("home/.cargo/credentials");
2222
t!(fs::create_dir_all(credentials.parent().unwrap()));
2323
t!(t!(File::create(&credentials)).write_all(br#"
24-
[alternative]
24+
[registries.alternative]
2525
token = "api-token"
2626
"#));
2727

tests/login.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ fn check_token(expected_token: &str, registry: Option<&str>) -> bool {
5353
// A registry has been provided, so check that the token exists in a
5454
// table for the registry.
5555
(Some(registry), toml::Value::Table(table)) => {
56-
table.get(registry).and_then(|registry_table| {
56+
table.get("registries")
57+
.and_then(|registries_table| registries_table.get(registry))
58+
.and_then(|registry_table| {
5759
match registry_table.get("token") {
5860
Some(&toml::Value::String(ref token)) => Some(token.as_str().to_string()),
5961
_ => None,
@@ -62,7 +64,9 @@ fn check_token(expected_token: &str, registry: Option<&str>) -> bool {
6264
},
6365
// There is no registry provided, so check the global token instead.
6466
(None, toml::Value::Table(table)) => {
65-
table.get("token").and_then(|v| {
67+
table.get("registry")
68+
.and_then(|registry_table| registry_table.get("token"))
69+
.and_then(|v| {
6670
match v {
6771
&toml::Value::String(ref token) => Some(token.as_str().to_string()),
6872
_ => None,

tests/publish.rs

+67-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ extern crate hamcrest;
44
extern crate tar;
55

66
use std::io::prelude::*;
7-
use std::fs::File;
7+
use std::fs::{self, File};
88
use std::io::SeekFrom;
99

1010
use cargotest::ChannelChanger;
@@ -70,6 +70,72 @@ See [..]
7070
}
7171
}
7272

73+
#[test]
74+
fn old_token_location() {
75+
publish::setup();
76+
77+
// publish::setup puts a token in this file.
78+
fs::remove_file(paths::root().join(".cargo/config")).unwrap();
79+
80+
let credentials = paths::root().join("home/.cargo/credentials");
81+
File::create(credentials)
82+
.unwrap()
83+
.write_all(br#"
84+
token = "api-token"
85+
"#)
86+
.unwrap();
87+
88+
let p = project("foo")
89+
.file("Cargo.toml", r#"
90+
[project]
91+
name = "foo"
92+
version = "0.0.1"
93+
authors = []
94+
license = "MIT"
95+
description = "foo"
96+
"#)
97+
.file("src/main.rs", "fn main() {}")
98+
.build();
99+
100+
assert_that(p.cargo("publish").arg("--no-verify")
101+
.arg("--index").arg(publish::registry().to_string()),
102+
execs().with_status(0).with_stderr(&format!("\
103+
[UPDATING] registry `{reg}`
104+
[WARNING] manifest has no documentation, [..]
105+
See [..]
106+
[PACKAGING] foo v0.0.1 ({dir})
107+
[UPLOADING] foo v0.0.1 ({dir})
108+
",
109+
dir = p.url(),
110+
reg = publish::registry())));
111+
112+
let mut f = File::open(&publish::upload_path().join("api/v1/crates/new")).unwrap();
113+
// Skip the metadata payload and the size of the tarball
114+
let mut sz = [0; 4];
115+
assert_eq!(f.read(&mut sz).unwrap(), 4);
116+
let sz = ((sz[0] as u32) << 0) |
117+
((sz[1] as u32) << 8) |
118+
((sz[2] as u32) << 16) |
119+
((sz[3] as u32) << 24);
120+
f.seek(SeekFrom::Current(sz as i64 + 4)).unwrap();
121+
122+
// Verify the tarball
123+
let mut rdr = GzDecoder::new(f);
124+
assert_eq!(rdr.header().unwrap().filename().unwrap(), b"foo-0.0.1.crate");
125+
let mut contents = Vec::new();
126+
rdr.read_to_end(&mut contents).unwrap();
127+
let mut ar = Archive::new(&contents[..]);
128+
for file in ar.entries().unwrap() {
129+
let file = file.unwrap();
130+
let fname = file.header().path_bytes();
131+
let fname = &*fname;
132+
assert!(fname == b"foo-0.0.1/Cargo.toml" ||
133+
fname == b"foo-0.0.1/Cargo.toml.orig" ||
134+
fname == b"foo-0.0.1/src/main.rs",
135+
"unexpected filename: {:?}", file.header().path());
136+
}
137+
}
138+
73139
// TODO: Deprecated
74140
// remove once it has been decided --host can be removed
75141
#[test]

0 commit comments

Comments
 (0)