Skip to content

Commit 4b70f14

Browse files
committed
Load credentials only when needed
Credentials are always loaded, even if these are not used. If access to confidential files such as credentials is not given, `cargo build` fails despite not using credentials. Fixes #7624.
1 parent 6e1ca92 commit 4b70f14

File tree

5 files changed

+92
-28
lines changed

5 files changed

+92
-28
lines changed

src/bin/cargo/commands/publish.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ pub fn cli() -> App {
2626
}
2727

2828
pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
29+
config.load_credentials()?;
30+
2931
let registry = args.registry(config)?;
3032
let ws = args.workspace(config)?;
3133
let index = args.index(config)?;

src/cargo/util/config/mod.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,6 @@ impl Config {
746746
})
747747
.chain_err(|| "could not load Cargo configuration")?;
748748

749-
self.load_credentials(&mut cfg)?;
750749
match cfg {
751750
CV::Table(map, _) => Ok(map),
752751
_ => unreachable!(),
@@ -979,9 +978,8 @@ impl Config {
979978
Ok(url)
980979
}
981980

982-
/// Loads credentials config from the credentials file into the `ConfigValue` object, if
983-
/// present.
984-
fn load_credentials(&self, cfg: &mut ConfigValue) -> CargoResult<()> {
981+
/// Loads credentials config from the credentials file, if present.
982+
pub fn load_credentials(&mut self) -> CargoResult<()> {
985983
let home_path = self.home_path.clone().into_path_unlocked();
986984
let credentials = match self.get_file_path(&home_path, "credentials", true)? {
987985
Some(credentials) => credentials,
@@ -1006,7 +1004,28 @@ impl Config {
10061004
}
10071005
}
10081006

1009-
cfg.merge(value, true)?;
1007+
if let CV::Table(mut map, _) = value {
1008+
if map.contains_key("registry") {
1009+
if let Some(mut new_map) = self.values_mut()?.remove("registry") {
1010+
let token = map.remove("registry").unwrap();
1011+
new_map.merge(token, true)?;
1012+
self.values_mut()?.insert("registry".into(), new_map);
1013+
} else {
1014+
self.values_mut()?
1015+
.insert("registry".into(), map.remove("registry").unwrap());
1016+
}
1017+
}
1018+
if map.contains_key("registries") {
1019+
if let Some(mut new_map) = self.values_mut()?.remove("registries") {
1020+
let token = map.remove("registries").unwrap();
1021+
new_map.merge(token, true)?;
1022+
self.values_mut()?.insert("registries".into(), new_map);
1023+
} else {
1024+
self.values_mut()?
1025+
.insert("registries".into(), map.remove("registries").unwrap());
1026+
}
1027+
}
1028+
}
10101029

10111030
Ok(())
10121031
}

tests/testsuite/build.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2237,6 +2237,32 @@ fn recompile_space_in_name() {
22372237
foo.cargo("build").with_stdout("").run();
22382238
}
22392239

2240+
#[cfg(unix)]
2241+
#[cargo_test]
2242+
fn credentials_is_unreadable() {
2243+
use cargo_test_support::paths::home;
2244+
use std::os::unix::prelude::*;
2245+
let p = project()
2246+
.file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
2247+
.file("src/lib.rs", "")
2248+
.build();
2249+
2250+
let credentials = home().join(".cargo/credentials");
2251+
t!(fs::create_dir_all(credentials.parent().unwrap()));
2252+
t!(t!(File::create(&credentials)).write_all(
2253+
br#"
2254+
[registry]
2255+
token = "api-token"
2256+
"#
2257+
));
2258+
let stat = fs::metadata(credentials.as_path()).unwrap();
2259+
let mut perms = stat.permissions();
2260+
perms.set_mode(0o000);
2261+
fs::set_permissions(credentials, perms.clone()).unwrap();
2262+
2263+
p.cargo("build").run();
2264+
}
2265+
22402266
#[cfg(unix)]
22412267
#[cargo_test]
22422268
fn ignore_bad_directories() {

tests/testsuite/login.rs

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -111,28 +111,6 @@ fn credentials_work_with_extension() {
111111
assert!(check_token(TOKEN, None));
112112
}
113113

114-
#[cargo_test]
115-
fn credentials_ambiguous_filename() {
116-
registry::init();
117-
setup_new_credentials();
118-
setup_new_credentials_toml();
119-
120-
cargo_process("login --host")
121-
.arg(registry_url().to_string())
122-
.arg(TOKEN)
123-
.with_stderr_contains(
124-
"\
125-
[WARNING] Both `[..]/credentials` and `[..]/credentials.toml` exist. Using `[..]/credentials`
126-
",
127-
)
128-
.run();
129-
130-
// It should use the value from the one without the extension
131-
// for backwards compatibility. check_token explicitly checks
132-
// 'credentials' without the extension, which is what we want.
133-
assert!(check_token(TOKEN, None));
134-
}
135-
136114
#[cargo_test]
137115
fn login_with_old_and_new_credentials() {
138116
setup_new_credentials();
@@ -161,7 +139,9 @@ fn new_credentials_is_used_instead_old() {
161139
.arg(TOKEN)
162140
.run();
163141

164-
let config = Config::new(Shell::new(), cargo_home(), cargo_home());
142+
let mut config = Config::new(Shell::new(), cargo_home(), cargo_home());
143+
let _ = config.values();
144+
let _ = config.load_credentials();
165145

166146
let token = config.get_string("registry.token").unwrap().map(|p| p.val);
167147
assert_eq!(token.unwrap(), TOKEN);

tests/testsuite/publish.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,3 +1261,40 @@ repository = "foo"
12611261
)],
12621262
);
12631263
}
1264+
1265+
#[cargo_test]
1266+
fn credentials_ambiguous_filename() {
1267+
registry::init();
1268+
1269+
let credentials_toml = paths::home().join(".cargo/credentials.toml");
1270+
File::create(&credentials_toml)
1271+
.unwrap()
1272+
.write_all(br#"token = "api-token""#)
1273+
.unwrap();
1274+
1275+
let p = project()
1276+
.file(
1277+
"Cargo.toml",
1278+
r#"
1279+
[project]
1280+
name = "foo"
1281+
version = "0.0.1"
1282+
authors = []
1283+
license = "MIT"
1284+
description = "foo"
1285+
"#,
1286+
)
1287+
.file("src/main.rs", "fn main() {}")
1288+
.build();
1289+
1290+
p.cargo("publish --no-verify --index")
1291+
.arg(registry_url().to_string())
1292+
.with_stderr_contains(
1293+
"\
1294+
[WARNING] Both `[..]/credentials` and `[..]/credentials.toml` exist. Using `[..]/credentials`
1295+
",
1296+
)
1297+
.run();
1298+
1299+
validate_upload_foo();
1300+
}

0 commit comments

Comments
 (0)