From d6cc0fb1923aec26f64c8751d3ddaaef43f30df2 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 4 Jun 2025 12:46:35 -0500 Subject: [PATCH 1/5] test(package): Prep for forking tests for stable --- tests/testsuite/package.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs index 2ce6d322b4e..a7e213f8fb4 100644 --- a/tests/testsuite/package.rs +++ b/tests/testsuite/package.rs @@ -6886,7 +6886,7 @@ fn registry_inferred_from_unique_option() { } #[cargo_test] -fn registry_not_inferred_because_of_conflict() { +fn registry_not_inferred_because_of_conflict_nightly() { let alt_reg = registry::RegistryBuilder::new() .http_api() .http_index() @@ -7074,7 +7074,7 @@ fn registry_inference_ignores_unpublishable() { } #[cargo_test] -fn registry_not_inferred_because_of_multiple_options() { +fn registry_not_inferred_because_of_multiple_options_nightly() { let _alt_reg = registry::RegistryBuilder::new() .http_api() .http_index() @@ -7156,7 +7156,7 @@ fn registry_not_inferred_because_of_multiple_options() { } #[cargo_test] -fn registry_not_inferred_because_of_mismatch() { +fn registry_not_inferred_because_of_mismatch_nightly() { let _alt_reg = registry::RegistryBuilder::new() .http_api() .http_index() From 68f0c653ca78de7684c81c92d83a3c5637330b38 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 4 Jun 2025 12:59:10 -0500 Subject: [PATCH 2/5] test(package): Show stable behavior for -Zpackage-workspace --- tests/testsuite/package.rs | 208 +++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs index a7e213f8fb4..e584d1929e6 100644 --- a/tests/testsuite/package.rs +++ b/tests/testsuite/package.rs @@ -6885,6 +6885,75 @@ fn registry_inferred_from_unique_option() { .run(); } +#[cargo_test] +fn registry_not_inferred_because_of_conflict() { + let _alt_reg = registry::RegistryBuilder::new() + .http_api() + .http_index() + .alternative() + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["dep", "main"] + "#, + ) + .file( + "main/Cargo.toml", + r#" + [package] + name = "main" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "main" + repository = "bar" + publish = ["alternative"] + + [dependencies] + dep = { path = "../dep", version = "0.1.0", registry = "alternative" } + "#, + ) + .file("main/src/main.rs", "fn main() {}") + .file( + "dep/Cargo.toml", + r#" + [package] + name = "dep" + version = "0.1.0" + edition = "2015" + authors = [] + license = "MIT" + description = "dep" + repository = "bar" + publish = ["alternative2"] + "#, + ) + .file("dep/src/lib.rs", "") + .build(); + + p.cargo("package") + .with_status(101) + .with_stderr_data(str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[ERROR] failed to prepare local package for uploading + +Caused by: + no matching package named `dep` found + location searched: `alternative` index + required by package `main v0.0.1 ([ROOT]/foo/main)` + +"#]]) + .run(); +} + #[cargo_test] fn registry_not_inferred_because_of_conflict_nightly() { let alt_reg = registry::RegistryBuilder::new() @@ -7073,6 +7142,75 @@ fn registry_inference_ignores_unpublishable() { .run(); } +#[cargo_test] +fn registry_not_inferred_because_of_multiple_options() { + let _alt_reg = registry::RegistryBuilder::new() + .http_api() + .http_index() + .alternative() + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["dep", "main"] + "#, + ) + .file( + "main/Cargo.toml", + r#" + [package] + name = "main" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "main" + repository = "bar" + publish = ["alternative", "alternative2"] + + [dependencies] + dep = { path = "../dep", version = "0.1.0", registry = "alternative" } + "#, + ) + .file("main/src/main.rs", "fn main() {}") + .file( + "dep/Cargo.toml", + r#" + [package] + name = "dep" + version = "0.1.0" + edition = "2015" + authors = [] + license = "MIT" + description = "dep" + repository = "bar" + publish = ["alternative", "alternative2"] + "#, + ) + .file("dep/src/lib.rs", "") + .build(); + + p.cargo("package") + .with_status(101) + .with_stderr_data(str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[ERROR] failed to prepare local package for uploading + +Caused by: + no matching package named `dep` found + location searched: `alternative` index + required by package `main v0.0.1 ([ROOT]/foo/main)` + +"#]]) + .run(); +} + #[cargo_test] fn registry_not_inferred_because_of_multiple_options_nightly() { let _alt_reg = registry::RegistryBuilder::new() @@ -7155,6 +7293,76 @@ fn registry_not_inferred_because_of_multiple_options_nightly() { .run(); } +#[cargo_test] +fn registry_not_inferred_because_of_mismatch() { + let _alt_reg = registry::RegistryBuilder::new() + .http_api() + .http_index() + .alternative() + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["dep", "main"] + "#, + ) + .file( + "main/Cargo.toml", + r#" + [package] + name = "main" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "main" + repository = "bar" + publish = ["alternative"] + + [dependencies] + dep = { path = "../dep", version = "0.1.0", registry = "alternative" } + "#, + ) + .file("main/src/main.rs", "fn main() {}") + // No `publish` field means "any registry", but the presence of this package + // will stop us from inferring a registry. + .file( + "dep/Cargo.toml", + r#" + [package] + name = "dep" + version = "0.1.0" + edition = "2015" + authors = [] + license = "MIT" + description = "dep" + repository = "bar" + "#, + ) + .file("dep/src/lib.rs", "") + .build(); + + p.cargo("package") + .with_status(101) + .with_stderr_data(str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[ERROR] failed to prepare local package for uploading + +Caused by: + no matching package named `dep` found + location searched: `alternative` index + required by package `main v0.0.1 ([ROOT]/foo/main)` + +"#]]) + .run(); +} + #[cargo_test] fn registry_not_inferred_because_of_mismatch_nightly() { let _alt_reg = registry::RegistryBuilder::new() From 4a92ad1241a04b2c0f6909a8252c8a40751aa272 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 4 Jun 2025 13:08:59 -0500 Subject: [PATCH 3/5] test(package): Better characterize the -Zpackage-workspace behavior change --- tests/testsuite/package.rs | 216 ++++++++++++++++++++++++++++++++++++- 1 file changed, 215 insertions(+), 1 deletion(-) diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs index e584d1929e6..4bde6b35770 100644 --- a/tests/testsuite/package.rs +++ b/tests/testsuite/package.rs @@ -6950,6 +6950,56 @@ Caused by: location searched: `alternative` index required by package `main v0.0.1 ([ROOT]/foo/main)` +"#]]) + .run(); + + p.cargo("package --exclude-lockfile") + .with_status(101) + .with_stderr_data(str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep) +[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[ERROR] failed to verify package tarball + +Caused by: + no matching package named `dep` found + location searched: `alternative` index + required by package `main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1)` + +"#]]) + .run(); + + p.cargo("package --no-verify") + .with_status(101) + .with_stderr_data(str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[ERROR] failed to prepare local package for uploading + +Caused by: + no matching package named `dep` found + location searched: `alternative` index + required by package `main v0.0.1 ([ROOT]/foo/main)` + +"#]]) + .run(); + + p.cargo("package --exclude-lockfile --no-verify") + .with_status(0) + .with_stderr_data(str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) + "#]]) .run(); } @@ -7011,6 +7061,33 @@ fn registry_not_inferred_because_of_conflict_nightly() { .with_stderr_data(str![[r#" [ERROR] conflicts between `package.publish` fields in the selected packages +"#]]) + .run(); + + p.cargo("package --exclude-lockfile -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] conflicts between `package.publish` fields in the selected packages + +"#]]) + .run(); + + p.cargo("package --no-verify -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] conflicts between `package.publish` fields in the selected packages + +"#]]) + .run(); + + p.cargo("package --exclude-lockfile --no-verify -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] conflicts between `package.publish` fields in the selected packages + "#]]) .run(); @@ -7193,7 +7270,29 @@ fn registry_not_inferred_because_of_multiple_options() { .file("dep/src/lib.rs", "") .build(); - p.cargo("package") + p.cargo("package --exclude-lockfile") + .with_status(101) + .with_stderr_data(str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep) +[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[ERROR] failed to verify package tarball + +Caused by: + no matching package named `dep` found + location searched: `alternative` index + required by package `main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1)` + +"#]]) + .run(); + + p.cargo("package --no-verify") .with_status(101) .with_stderr_data(str![[r#" [PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) @@ -7207,6 +7306,17 @@ Caused by: location searched: `alternative` index required by package `main v0.0.1 ([ROOT]/foo/main)` +"#]]) + .run(); + + p.cargo("package --exclude-lockfile --no-verify") + .with_status(0) + .with_stderr_data(str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) + "#]]) .run(); } @@ -7268,6 +7378,33 @@ fn registry_not_inferred_because_of_multiple_options_nightly() { .with_stderr_data(str![[r#" [ERROR] --registry is required to disambiguate between "alternative" or "alternative2" registries +"#]]) + .run(); + + p.cargo("package --exclude-lockfile -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] --registry is required to disambiguate between "alternative" or "alternative2" registries + +"#]]) + .run(); + + p.cargo("package --no-verify -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] --registry is required to disambiguate between "alternative" or "alternative2" registries + +"#]]) + .run(); + + p.cargo("package --exclude-lockfile --no-verify -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] --registry is required to disambiguate between "alternative" or "alternative2" registries + "#]]) .run(); @@ -7359,6 +7496,56 @@ Caused by: location searched: `alternative` index required by package `main v0.0.1 ([ROOT]/foo/main)` +"#]]) + .run(); + + p.cargo("package --exclude-lockfile") + .with_status(101) + .with_stderr_data(str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep) +[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[ERROR] failed to verify package tarball + +Caused by: + no matching package named `dep` found + location searched: `alternative` index + required by package `main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1)` + +"#]]) + .run(); + + p.cargo("package --no-verify") + .with_status(101) + .with_stderr_data(str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[ERROR] failed to prepare local package for uploading + +Caused by: + no matching package named `dep` found + location searched: `alternative` index + required by package `main v0.0.1 ([ROOT]/foo/main)` + +"#]]) + .run(); + + p.cargo("package --exclude-lockfile --no-verify") + .with_status(0) + .with_stderr_data(str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) + "#]]) .run(); } @@ -7421,6 +7608,33 @@ fn registry_not_inferred_because_of_mismatch_nightly() { .with_stderr_data(str![[r#" [ERROR] --registry is required because not all `package.publish` settings agree +"#]]) + .run(); + + p.cargo("package --exclude-lockfile -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] --registry is required because not all `package.publish` settings agree + +"#]]) + .run(); + + p.cargo("package --no-verify -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] --registry is required because not all `package.publish` settings agree + +"#]]) + .run(); + + p.cargo("package --exclude-lockfile --no-verify -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] --registry is required because not all `package.publish` settings agree + "#]]) .run(); From 778f3513e34b1db28f8e47d11d1cbf154c0b2045 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 4 Jun 2025 13:18:00 -0500 Subject: [PATCH 4/5] refactor(package): Switch to positive logic --- src/cargo/ops/cargo_package/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cargo/ops/cargo_package/mod.rs b/src/cargo/ops/cargo_package/mod.rs index bc35ea0c67f..63598320053 100644 --- a/src/cargo/ops/cargo_package/mod.rs +++ b/src/cargo/ops/cargo_package/mod.rs @@ -243,12 +243,12 @@ fn do_package<'a>( // The publish registry doesn't matter unless there are local dependencies, // so only try to get one if we need it. If they explicitly passed a // registry on the CLI, we check it no matter what. - let sid = if deps.has_no_dependencies() && opts.reg_or_index.is_none() { - None - } else { + let sid = if deps.has_dependencies() || opts.reg_or_index.is_some() { let sid = get_registry(ws.gctx(), &just_pkgs, opts.reg_or_index.clone())?; debug!("packaging for registry {}", sid); Some(sid) + } else { + None }; let reg_dir = ws.build_dir().join("package").join("tmp-registry"); sid.map(|sid| TmpRegistry::new(ws.gctx(), reg_dir, sid)) @@ -377,10 +377,10 @@ impl LocalDependencies { .collect() } - pub fn has_no_dependencies(&self) -> bool { + pub fn has_dependencies(&self) -> bool { self.graph .iter() - .all(|node| self.graph.edges(node).next().is_none()) + .any(|node| self.graph.edges(node).next().is_some()) } } From 094ef50e944f17e5138d27b81278270f1ba5327a Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 4 Jun 2025 13:21:12 -0500 Subject: [PATCH 5/5] fix(package): Skip registry check if its not needed I believe this brings makes it so `cargo package -Zpackage-workspace` no longer has a behavior change compared to `cargo package`. --- src/cargo/ops/cargo_package/mod.rs | 7 +++++-- tests/testsuite/package.rs | 18 ++++++++++++------ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/cargo/ops/cargo_package/mod.rs b/src/cargo/ops/cargo_package/mod.rs index 63598320053..a7d053df1e7 100644 --- a/src/cargo/ops/cargo_package/mod.rs +++ b/src/cargo/ops/cargo_package/mod.rs @@ -240,10 +240,13 @@ fn do_package<'a>( let just_pkgs: Vec<_> = pkgs.iter().map(|p| p.0).collect(); let mut local_reg = if ws.gctx().cli_unstable().package_workspace { - // The publish registry doesn't matter unless there are local dependencies, + // The publish registry doesn't matter unless there are local dependencies that will be + // resolved, // so only try to get one if we need it. If they explicitly passed a // registry on the CLI, we check it no matter what. - let sid = if deps.has_dependencies() || opts.reg_or_index.is_some() { + let sid = if (deps.has_dependencies() && (opts.include_lockfile || opts.verify)) + || opts.reg_or_index.is_some() + { let sid = get_registry(ws.gctx(), &just_pkgs, opts.reg_or_index.clone())?; debug!("packaging for registry {}", sid); Some(sid) diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs index 4bde6b35770..525c2f78c30 100644 --- a/tests/testsuite/package.rs +++ b/tests/testsuite/package.rs @@ -7084,9 +7084,11 @@ fn registry_not_inferred_because_of_conflict_nightly() { p.cargo("package --exclude-lockfile --no-verify -Zpackage-workspace") .masquerade_as_nightly_cargo(&["package-workspace"]) - .with_status(101) .with_stderr_data(str![[r#" -[ERROR] conflicts between `package.publish` fields in the selected packages +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) "#]]) .run(); @@ -7401,9 +7403,11 @@ fn registry_not_inferred_because_of_multiple_options_nightly() { p.cargo("package --exclude-lockfile --no-verify -Zpackage-workspace") .masquerade_as_nightly_cargo(&["package-workspace"]) - .with_status(101) .with_stderr_data(str![[r#" -[ERROR] --registry is required to disambiguate between "alternative" or "alternative2" registries +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) "#]]) .run(); @@ -7631,9 +7635,11 @@ fn registry_not_inferred_because_of_mismatch_nightly() { p.cargo("package --exclude-lockfile --no-verify -Zpackage-workspace") .masquerade_as_nightly_cargo(&["package-workspace"]) - .with_status(101) .with_stderr_data(str![[r#" -[ERROR] --registry is required because not all `package.publish` settings agree +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) "#]]) .run();