Skip to content

Commit 96f8d6c

Browse files
committedApr 12, 2023
Auto merge of #11949 - ehuss:logout-default, r=epage
Use registry.default for login/logout This changes `cargo login` and `cargo logout` to use the registry configured at `registry.default` as the registry instead of crates.io. For `cargo login`, this was an unintentional regression from #6466. The documentation has always stated that it will use the default registry. This makes the command more in line with other registry-involving commands. There are still some inconsistencies. These commands use the default if not specified: * `cargo init` * `cargo new` * `cargo owner` * `cargo search` * `cargo yank` * `cargo publish` uses the default, but will also look at the `publish` field `Cargo.toml` and use that if the registry is not specified. These commands would always use crates.io if `--registry` is not specified: * `cargo login` * `cargo logout` * `cargo install` I'm a bit uncertain how to proceed, since this is technically a breaking change particularly if someone has scripted it. I suspect that the number of users that use `registry.default` is very small, and those that script `cargo login` are even smaller, and thus the intersection is probably small or nonexistent. However, there is some risk here.
2 parents 1ce01c5 + a9e0b50 commit 96f8d6c

File tree

8 files changed

+202
-47
lines changed

8 files changed

+202
-47
lines changed
 

‎src/bin/cargo/commands/login.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,11 @@ pub fn cli() -> Command {
3434
}
3535

3636
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
37+
let registry = args.registry(config)?;
3738
ops::registry_login(
3839
config,
3940
args.get_one::<String>("token").map(|s| s.as_str().into()),
40-
args.get_one("registry").map(String::as_str),
41+
registry.as_deref(),
4142
args.flag("generate-keypair"),
4243
args.flag("secret-key"),
4344
args.get_one("key-subject").map(String::as_str),

‎src/bin/cargo/commands/logout.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
1515
.cli_unstable()
1616
.fail_if_stable_command(config, "logout", 8933)?;
1717
}
18-
ops::registry_logout(
19-
config,
20-
args.get_one::<String>("registry").map(String::as_str),
21-
)?;
18+
let registry = args.registry(config)?;
19+
ops::registry_logout(config, registry.as_deref())?;
2220
Ok(())
2321
}

‎src/cargo/sources/registry/http_remote.rs

+1
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,7 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> {
551551
if self.auth_required {
552552
return Poll::Ready(err.context(auth::AuthorizationError {
553553
sid: self.source_id.clone(),
554+
default_registry: self.config.default_registry()?,
554555
login_url: self.login_url.clone(),
555556
reason: auth::AuthorizationErrorReason::TokenRejected,
556557
}));

‎src/cargo/util/auth.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,8 @@ impl fmt::Display for AuthorizationErrorReason {
347347
pub struct AuthorizationError {
348348
/// Url that was attempted
349349
pub sid: SourceId,
350+
/// The `registry.default` config value.
351+
pub default_registry: Option<String>,
350352
/// Url where the user could log in.
351353
pub login_url: Option<Url>,
352354
/// Specific reason indicating what failed
@@ -356,9 +358,14 @@ impl Error for AuthorizationError {}
356358
impl fmt::Display for AuthorizationError {
357359
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
358360
if self.sid.is_crates_io() {
361+
let args = if self.default_registry.is_some() {
362+
" --registry crates-io"
363+
} else {
364+
""
365+
};
359366
write!(
360367
f,
361-
"{}, please run `cargo login`\nor use environment variable CARGO_REGISTRY_TOKEN",
368+
"{}, please run `cargo login{args}`\nor use environment variable CARGO_REGISTRY_TOKEN",
362369
self.reason
363370
)
364371
} else if let Some(name) = self.sid.alt_registry_key() {
@@ -421,6 +428,7 @@ pub fn auth_token(
421428
Some(token) => Ok(token.expose()),
422429
None => Err(AuthorizationError {
423430
sid: sid.clone(),
431+
default_registry: config.default_registry()?,
424432
login_url: login_url.cloned(),
425433
reason: AuthorizationErrorReason::TokenMissing,
426434
}

‎tests/testsuite/login.rs

+46-11
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,15 @@ fn setup_new_credentials_at(config: PathBuf) {
2727
));
2828
}
2929

30-
fn check_token(expected_token: &str, registry: Option<&str>) -> bool {
30+
/// Asserts whether or not the token is set to the given value for the given registry.
31+
pub fn check_token(expected_token: Option<&str>, registry: Option<&str>) {
3132
let credentials = credentials_toml();
3233
assert!(credentials.is_file());
3334

3435
let contents = fs::read_to_string(&credentials).unwrap();
3536
let toml: toml::Table = contents.parse().unwrap();
3637

37-
let token = match registry {
38+
let actual_token = match registry {
3839
// A registry has been provided, so check that the token exists in a
3940
// table for the registry.
4041
Some(registry) => toml
@@ -54,10 +55,15 @@ fn check_token(expected_token: &str, registry: Option<&str>) -> bool {
5455
}),
5556
};
5657

57-
if let Some(token_val) = token {
58-
token_val == expected_token
59-
} else {
60-
false
58+
match (actual_token, expected_token) {
59+
(None, None) => {}
60+
(Some(actual), Some(expected)) => assert_eq!(actual, expected),
61+
(None, Some(expected)) => {
62+
panic!("expected `{registry:?}` to be `{expected}`, but was not set")
63+
}
64+
(Some(actual), None) => {
65+
panic!("expected `{registry:?}` to be unset, but was set to `{actual}`")
66+
}
6167
}
6268
}
6369

@@ -75,10 +81,10 @@ fn registry_credentials() {
7581
cargo_process("login --registry").arg(reg).arg(TOKEN).run();
7682

7783
// Ensure that we have not updated the default token
78-
assert!(check_token(ORIGINAL_TOKEN, None));
84+
check_token(Some(ORIGINAL_TOKEN), None);
7985

8086
// Also ensure that we get the new token for the registry
81-
assert!(check_token(TOKEN, Some(reg)));
87+
check_token(Some(TOKEN), Some(reg));
8288

8389
let reg2 = "alternative2";
8490
cargo_process("login --registry")
@@ -88,9 +94,9 @@ fn registry_credentials() {
8894

8995
// Ensure not overwriting 1st alternate registry token with
9096
// 2nd alternate registry token (see rust-lang/cargo#7701).
91-
assert!(check_token(ORIGINAL_TOKEN, None));
92-
assert!(check_token(TOKEN, Some(reg)));
93-
assert!(check_token(TOKEN2, Some(reg2)));
97+
check_token(Some(ORIGINAL_TOKEN), None);
98+
check_token(Some(TOKEN), Some(reg));
99+
check_token(Some(TOKEN2), Some(reg2));
94100
}
95101

96102
#[cargo_test]
@@ -367,3 +373,32 @@ fn login_with_generate_asymmetric_token() {
367373
let credentials = fs::read_to_string(&credentials).unwrap();
368374
assert!(credentials.contains("secret-key = \"k3.secret."));
369375
}
376+
377+
#[cargo_test]
378+
fn default_registry_configured() {
379+
// When registry.default is set, login should use that one when
380+
// --registry is not used.
381+
let _alternative = RegistryBuilder::new().alternative().build();
382+
let cargo_home = paths::home().join(".cargo");
383+
cargo_util::paths::append(
384+
&cargo_home.join("config"),
385+
br#"
386+
[registry]
387+
default = "alternative"
388+
"#,
389+
)
390+
.unwrap();
391+
392+
cargo_process("login")
393+
.arg("a-new-token")
394+
.with_stderr(
395+
"\
396+
[UPDATING] `alternative` index
397+
[LOGIN] token for `alternative` saved
398+
",
399+
)
400+
.run();
401+
402+
check_token(None, None);
403+
check_token(Some("a-new-token"), Some("alternative"));
404+
}

‎tests/testsuite/logout.rs

+59-29
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
//! Tests for the `cargo logout` command.
22
3-
use cargo_test_support::install::cargo_home;
3+
use super::login::check_token;
4+
use cargo_test_support::paths::{self, CargoPathExt};
45
use cargo_test_support::registry::TestRegistry;
56
use cargo_test_support::{cargo_process, registry};
6-
use std::fs;
77

88
#[cargo_test]
99
fn gated() {
@@ -21,32 +21,9 @@ the `cargo logout` command.
2121
.run();
2222
}
2323

24-
/// Checks whether or not the token is set for the given token.
25-
fn check_config_token(registry: Option<&str>, should_be_set: bool) {
26-
let credentials = cargo_home().join("credentials.toml");
27-
let contents = fs::read_to_string(&credentials).unwrap();
28-
let toml: toml::Table = contents.parse().unwrap();
29-
if let Some(registry) = registry {
30-
assert_eq!(
31-
toml.get("registries")
32-
.and_then(|registries| registries.get(registry))
33-
.and_then(|registry| registry.get("token"))
34-
.is_some(),
35-
should_be_set
36-
);
37-
} else {
38-
assert_eq!(
39-
toml.get("registry")
40-
.and_then(|registry| registry.get("token"))
41-
.is_some(),
42-
should_be_set
43-
);
44-
}
45-
}
46-
4724
fn simple_logout_test(registry: &TestRegistry, reg: Option<&str>, flag: &str, note: &str) {
4825
let msg = reg.unwrap_or("crates-io");
49-
check_config_token(reg, true);
26+
check_token(Some(registry.token()), reg);
5027
let mut cargo = cargo_process(&format!("logout -Z unstable-options {}", flag));
5128
if reg.is_none() {
5229
cargo.replace_crates_io(registry.index_url());
@@ -61,7 +38,7 @@ If you need to revoke the token, visit {note} and follow the instructions there.
6138
"
6239
))
6340
.run();
64-
check_config_token(reg, false);
41+
check_token(None, reg);
6542

6643
let mut cargo = cargo_process(&format!("logout -Z unstable-options {}", flag));
6744
if reg.is_none() {
@@ -71,11 +48,11 @@ If you need to revoke the token, visit {note} and follow the instructions there.
7148
.masquerade_as_nightly_cargo(&["cargo-logout"])
7249
.with_stderr(&format!("[LOGOUT] not currently logged in to `{msg}`"))
7350
.run();
74-
check_config_token(reg, false);
51+
check_token(None, reg);
7552
}
7653

7754
#[cargo_test]
78-
fn default_registry() {
55+
fn default_registry_unconfigured() {
7956
let registry = registry::init();
8057
simple_logout_test(&registry, None, "", "<https://crates.io/me>");
8158
}
@@ -89,4 +66,57 @@ fn other_registry() {
8966
"--registry alternative",
9067
"the `alternative` website",
9168
);
69+
// It should not touch crates.io.
70+
check_token(Some("sekrit"), None);
71+
}
72+
73+
#[cargo_test]
74+
fn default_registry_configured() {
75+
// When registry.default is set, logout should use that one when
76+
// --registry is not used.
77+
let cargo_home = paths::home().join(".cargo");
78+
cargo_home.mkdir_p();
79+
cargo_util::paths::write(
80+
&cargo_home.join("config.toml"),
81+
r#"
82+
[registry]
83+
default = "dummy-registry"
84+
85+
[registries.dummy-registry]
86+
index = "https://127.0.0.1/index"
87+
"#,
88+
)
89+
.unwrap();
90+
cargo_util::paths::write(
91+
&cargo_home.join("credentials.toml"),
92+
r#"
93+
[registry]
94+
token = "crates-io-token"
95+
96+
[registries.dummy-registry]
97+
token = "dummy-token"
98+
"#,
99+
)
100+
.unwrap();
101+
check_token(Some("dummy-token"), Some("dummy-registry"));
102+
check_token(Some("crates-io-token"), None);
103+
104+
cargo_process("logout -Zunstable-options")
105+
.masquerade_as_nightly_cargo(&["cargo-logout"])
106+
.with_stderr(
107+
"\
108+
[LOGOUT] token for `dummy-registry` has been removed from local storage
109+
[NOTE] This does not revoke the token on the registry server.
110+
If you need to revoke the token, visit the `dummy-registry` website \
111+
and follow the instructions there.
112+
",
113+
)
114+
.run();
115+
check_token(None, Some("dummy-registry"));
116+
check_token(Some("crates-io-token"), None);
117+
118+
cargo_process("logout -Zunstable-options")
119+
.masquerade_as_nightly_cargo(&["cargo-logout"])
120+
.with_stderr("[LOGOUT] not currently logged in to `dummy-registry`")
121+
.run();
92122
}

‎tests/testsuite/registry.rs

+82
Original file line numberDiff line numberDiff line change
@@ -3192,3 +3192,85 @@ required by package `foo v0.0.1 ([ROOT]/foo)`
31923192
]
31933193
);
31943194
}
3195+
3196+
#[cargo_test]
3197+
fn default_auth_error() {
3198+
// Check for the error message for an authentication error when default is set.
3199+
let crates_io = RegistryBuilder::new().http_api().build();
3200+
let _alternative = RegistryBuilder::new().http_api().alternative().build();
3201+
3202+
paths::home().join(".cargo/credentials.toml").rm_rf();
3203+
3204+
let p = project()
3205+
.file(
3206+
"Cargo.toml",
3207+
r#"
3208+
[package]
3209+
name = "foo"
3210+
version = "0.1.0"
3211+
license = "MIT"
3212+
description = "foo"
3213+
"#,
3214+
)
3215+
.file("src/lib.rs", "")
3216+
.build();
3217+
3218+
// Test output before setting the default.
3219+
p.cargo("publish --no-verify")
3220+
.replace_crates_io(crates_io.index_url())
3221+
.with_stderr(
3222+
"\
3223+
[UPDATING] crates.io index
3224+
error: no token found, please run `cargo login`
3225+
or use environment variable CARGO_REGISTRY_TOKEN
3226+
",
3227+
)
3228+
.with_status(101)
3229+
.run();
3230+
3231+
p.cargo("publish --no-verify --registry alternative")
3232+
.replace_crates_io(crates_io.index_url())
3233+
.with_stderr(
3234+
"\
3235+
[UPDATING] `alternative` index
3236+
error: no token found for `alternative`, please run `cargo login --registry alternative`
3237+
or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN
3238+
",
3239+
)
3240+
.with_status(101)
3241+
.run();
3242+
3243+
// Test the output with the default.
3244+
cargo_util::paths::append(
3245+
&cargo_home().join("config"),
3246+
br#"
3247+
[registry]
3248+
default = "alternative"
3249+
"#,
3250+
)
3251+
.unwrap();
3252+
3253+
p.cargo("publish --no-verify")
3254+
.replace_crates_io(crates_io.index_url())
3255+
.with_stderr(
3256+
"\
3257+
[UPDATING] `alternative` index
3258+
error: no token found for `alternative`, please run `cargo login --registry alternative`
3259+
or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN
3260+
",
3261+
)
3262+
.with_status(101)
3263+
.run();
3264+
3265+
p.cargo("publish --no-verify --registry crates-io")
3266+
.replace_crates_io(crates_io.index_url())
3267+
.with_stderr(
3268+
"\
3269+
[UPDATING] crates.io index
3270+
error: no token found, please run `cargo login --registry crates-io`
3271+
or use environment variable CARGO_REGISTRY_TOKEN
3272+
",
3273+
)
3274+
.with_status(101)
3275+
.run();
3276+
}

‎tests/testsuite/registry_auth.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! Tests for normal registry dependencies.
1+
//! Tests for registry authentication.
22
33
use cargo_test_support::registry::{Package, RegistryBuilder};
44
use cargo_test_support::{project, Execs, Project};

0 commit comments

Comments
 (0)
Please sign in to comment.