Skip to content

Commit 5c03433

Browse files
authored
feat: emit a warning when both package.publish and --index are specified (#16268)
Partially adresses #16231. ### What does this PR try to resolve? `cargo publish` will fail, if `--registry` is passed and that index isn't included in `package.publish` in Cargo.toml. However, as described in linked issue, `--index` bypasses that check and may cause unexpected publication of packages. This PR implements warning that is shown when `--index` and `package.publish` is set at the same time.
2 parents 9a30321 + d4a80f3 commit 5c03433

File tree

2 files changed

+96
-20
lines changed

2 files changed

+96
-20
lines changed

src/cargo/ops/registry/publish.rs

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -126,26 +126,7 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
126126
}
127127

128128
let just_pkgs: Vec<_> = pkgs.iter().map(|p| p.0).collect();
129-
let reg_or_index = match opts.reg_or_index.clone() {
130-
Some(r) => {
131-
validate_registry(&just_pkgs, Some(&r))?;
132-
Some(r)
133-
}
134-
None => {
135-
let reg = super::infer_registry(&just_pkgs)?;
136-
validate_registry(&just_pkgs, reg.as_ref())?;
137-
if let Some(RegistryOrIndex::Registry(registry)) = &reg {
138-
if registry != CRATES_IO_REGISTRY {
139-
// Don't warn for crates.io.
140-
opts.gctx.shell().note(&format!(
141-
"found `{}` as only allowed registry. Publishing to it automatically.",
142-
registry
143-
))?;
144-
}
145-
}
146-
reg
147-
}
148-
};
129+
let reg_or_index = resolve_registry_or_index(opts, &just_pkgs)?;
149130

150131
// This is only used to confirm that we can create a token before we build the package.
151132
// This causes the credential provider to be called an extra time, but keeps the same order of errors.
@@ -814,6 +795,46 @@ fn package_list(pkgs: impl IntoIterator<Item = PackageId>, final_sep: &str) -> S
814795
}
815796
}
816797

798+
fn resolve_registry_or_index(
799+
opts: &PublishOpts<'_>,
800+
just_pkgs: &[&Package],
801+
) -> CargoResult<Option<RegistryOrIndex>> {
802+
let opt_index_or_registry = opts.reg_or_index.clone();
803+
804+
let res = match opt_index_or_registry {
805+
ref r @ Some(ref registry_or_index) => {
806+
validate_registry(just_pkgs, r.as_ref())?;
807+
808+
let registry_is_specified_by_any_package = just_pkgs
809+
.iter()
810+
.any(|pkg| pkg.publish().as_ref().map(|v| v.len()).unwrap_or(0) > 0);
811+
812+
if registry_is_specified_by_any_package && registry_or_index.is_index() {
813+
opts.gctx.shell().warn(r#"`--index` will ignore registries set by `package.publish` in Cargo.toml, and may cause unexpected push to prohibited registry
814+
help: use `--registry` instead or set `publish = true` in Cargo.toml to suppress this warning"#)?;
815+
}
816+
817+
r.clone()
818+
}
819+
None => {
820+
let reg = super::infer_registry(&just_pkgs)?;
821+
validate_registry(&just_pkgs, reg.as_ref())?;
822+
if let Some(RegistryOrIndex::Registry(registry)) = &reg {
823+
if registry != CRATES_IO_REGISTRY {
824+
// Don't warn for crates.io.
825+
opts.gctx.shell().note(&format!(
826+
"found `{}` as only allowed registry. Publishing to it automatically.",
827+
registry
828+
))?;
829+
}
830+
}
831+
reg
832+
}
833+
};
834+
835+
Ok(res)
836+
}
837+
817838
fn validate_registry(pkgs: &[&Package], reg_or_index: Option<&RegistryOrIndex>) -> CargoResult<()> {
818839
let reg_name = match reg_or_index {
819840
Some(RegistryOrIndex::Registry(r)) => Some(r.as_str()),

tests/testsuite/publish.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,60 @@ fn publish_implicitly_to_only_allowed_registry() {
979979
);
980980
}
981981

982+
#[cargo_test]
983+
fn publish_when_both_publish_and_index_specified() {
984+
let registry = RegistryBuilder::new()
985+
.http_api()
986+
.http_index()
987+
.alternative()
988+
.build();
989+
990+
let p = project().build();
991+
992+
let _ = repo(&paths::root().join("foo"))
993+
.file(
994+
"Cargo.toml",
995+
r#"
996+
[package]
997+
name = "foo"
998+
version = "0.0.1"
999+
edition = "2015"
1000+
authors = []
1001+
license = "MIT"
1002+
description = "foo"
1003+
documentation = "foo"
1004+
homepage = "foo"
1005+
repository = "foo"
1006+
publish = ["registry"]
1007+
"#,
1008+
)
1009+
.file("src/main.rs", "fn main() {}")
1010+
.build();
1011+
1012+
p.cargo("publish")
1013+
.arg("--index")
1014+
.arg(registry.index_url().as_str())
1015+
.arg("--token")
1016+
.arg(registry.token())
1017+
.with_stderr_data(str![[r#"
1018+
[WARNING] `cargo publish --token` is deprecated in favor of using `cargo login` and environment variables
1019+
[WARNING] `--index` will ignore registries set by `package.publish` in Cargo.toml, and may cause unexpected push to prohibited registry
1020+
[HELP] use `--registry` instead or set `publish = true` in Cargo.toml to suppress this warning
1021+
[UPDATING] [..] index
1022+
[PACKAGING] foo v0.0.1 ([ROOT]/foo)
1023+
[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)
1024+
[VERIFYING] foo v0.0.1 ([ROOT]/foo)
1025+
[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)
1026+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
1027+
[UPLOADING] foo v0.0.1 ([ROOT]/foo)
1028+
[UPLOADED] foo v0.0.1 to registry [..]
1029+
[NOTE] waiting for foo v0.0.1 to be available at registry [..]
1030+
[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly
1031+
[PUBLISHED] foo v0.0.1 at registry [..]
1032+
"#]])
1033+
.run();
1034+
}
1035+
9821036
#[cargo_test]
9831037
fn publish_failed_with_index_and_only_allowed_registry() {
9841038
let registry = RegistryBuilder::new()
@@ -1014,6 +1068,7 @@ fn publish_failed_with_index_and_only_allowed_registry() {
10141068
.arg(registry.index_url().as_str())
10151069
.with_status(101)
10161070
.with_stderr_data(str![[r#"
1071+
...
10171072
[ERROR] command-line argument --index requires --token to be specified
10181073
10191074
"#]])

0 commit comments

Comments
 (0)