From efb300775a1d22d973e50a7efcef603b5d0f784a Mon Sep 17 00:00:00 2001 From: Joe Neeman Date: Thu, 1 May 2025 13:18:40 +0700 Subject: [PATCH 1/3] Add a failing test --- tests/testsuite/package.rs | 71 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs index ed12768cf1e..469a91cbfa4 100644 --- a/tests/testsuite/package.rs +++ b/tests/testsuite/package.rs @@ -5806,6 +5806,77 @@ features = ["foo"] ); } +#[cargo_test] +fn workspace_with_local_dev_deps() { + let crates_io = registry::init(); + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["main", "dev_dep"] + resolver = "3" + + [workspace.dependencies] + dev_dep = { path = "dev_dep", version = "0.0.1" } + "#, + ) + .file( + "main/Cargo.toml", + r#" + [package] + name = "main" + version = "0.0.1" + edition = "2024" + authors = [] + license = "MIT" + description = "main" + + [dev-dependencies] + dev_dep.workspace = true + "#, + ) + .file( + "dev_dep/Cargo.toml", + r#" + [package] + name = "dev_dep" + version = "0.0.1" + edition = "2024" + authors = [] + license = "MIT" + description = "main" + "#, + ) + .file("main/src/lib.rs", "") + .file("dev_dep/src/lib.rs", "") + .build(); + + p.cargo("package -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .replace_crates_io(crates_io.index_url()) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] dev_dep v0.0.1 ([ROOT]/foo/dev_dep) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] crates.io index +[ERROR] failed to prepare local package for uploading + +Caused by: + no matching package named `dev_dep` found + location searched: crates.io index + required by package `main v0.0.1 ([ROOT]/foo/main)` + +"#]]) + .with_status(101) + .run(); +} + fn workspace_with_local_deps_packaging_one_fails_project() -> Project { project() .file( From 54448a1a19aefa9a06748f1cc14e2e647e2f9c4a Mon Sep 17 00:00:00 2001 From: Joe Neeman Date: Thu, 1 May 2025 13:38:02 +0700 Subject: [PATCH 2/3] Only check for the registry if package-workspace is turned on. Without this, the upcoming change to stop stripping versioned dev-dependencies breaks the unpublished_cyclic_dev_dependencies test because the test setup replaces the registry. --- src/cargo/ops/cargo_package/mod.rs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/cargo/ops/cargo_package/mod.rs b/src/cargo/ops/cargo_package/mod.rs index 71d43bc0198..d1ef8716859 100644 --- a/src/cargo/ops/cargo_package/mod.rs +++ b/src/cargo/ops/cargo_package/mod.rs @@ -239,18 +239,17 @@ fn do_package<'a>( let deps = local_deps(pkgs.iter().map(|(p, f)| ((*p).clone(), f.clone()))); let just_pkgs: Vec<_> = pkgs.iter().map(|p| p.0).collect(); - // 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 = get_registry(ws.gctx(), &just_pkgs, opts.reg_or_index.clone())?; - debug!("packaging for registry {}", sid); - Some(sid) - }; - let mut local_reg = if ws.gctx().cli_unstable().package_workspace { + // 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 = get_registry(ws.gctx(), &just_pkgs, opts.reg_or_index.clone())?; + debug!("packaging for registry {}", sid); + Some(sid) + }; let reg_dir = ws.build_dir().join("package").join("tmp-registry"); sid.map(|sid| TmpRegistry::new(ws.gctx(), reg_dir, sid)) .transpose()? From faf7329c4ff6f75328b1bd489e2c825b28349b8c Mon Sep 17 00:00:00 2001 From: Joe Neeman Date: Thu, 1 May 2025 13:25:24 +0700 Subject: [PATCH 3/3] Only ignore dev-dependencies in dependency order if they have no version --- src/cargo/ops/cargo_package/mod.rs | 11 ++++++++--- tests/testsuite/package.rs | 14 +++++++------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/cargo/ops/cargo_package/mod.rs b/src/cargo/ops/cargo_package/mod.rs index d1ef8716859..fe750adb9f7 100644 --- a/src/cargo/ops/cargo_package/mod.rs +++ b/src/cargo/ops/cargo_package/mod.rs @@ -406,9 +406,14 @@ fn local_deps(packages: impl Iterator) -> LocalDependenc for (pkg, _payload) in packages.values() { graph.add(pkg.package_id()); for dep in pkg.dependencies() { - // Ignore local dev-dependencies because they aren't needed for intra-workspace - // lockfile generation or verification as they get stripped on publish. - if dep.kind() == DepKind::Development || !dep.source_id().is_path() { + // We're only interested in local (i.e. living in this workspace) dependencies. + if !dep.source_id().is_path() { + continue; + } + + // If local dev-dependencies don't have a version specified, they get stripped + // on publish so we should ignore them. + if dep.kind() == DepKind::Development && !dep.specified_req() { continue; }; diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs index 469a91cbfa4..e519fa18bcf 100644 --- a/tests/testsuite/package.rs +++ b/tests/testsuite/package.rs @@ -5865,15 +5865,15 @@ See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. [PACKAGING] main v0.0.1 ([ROOT]/foo/main) [UPDATING] crates.io index -[ERROR] failed to prepare local package for uploading - -Caused by: - no matching package named `dev_dep` found - location searched: crates.io index - required by package `main v0.0.1 ([ROOT]/foo/main)` +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] dev_dep v0.0.1 ([ROOT]/foo/dev_dep) +[COMPILING] dev_dep v0.0.1 ([ROOT]/foo/target/package/dev_dep-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] main v0.0.1 ([ROOT]/foo/main) +[COMPILING] main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) - .with_status(101) .run(); }