diff --git a/src/source_distribution.rs b/src/source_distribution.rs index 2b255ea13..bbfd71b45 100644 --- a/src/source_distribution.rs +++ b/src/source_distribution.rs @@ -15,7 +15,7 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::str; use toml_edit::DocumentMut; -use tracing::debug; +use tracing::{debug, trace}; /// Path dependency information. /// It may be in a different workspace than the root crate. @@ -185,6 +185,11 @@ fn add_crate_to_source_distribution( root_crate: bool, skip_cargo_toml: bool, ) -> Result<()> { + debug!( + "Getting cargo package file list for {}", + manifest_path.as_ref().display() + ); + let prefix = prefix.as_ref(); let manifest_path = manifest_path.as_ref(); let args = ["package", "--list", "--allow-dirty", "--manifest-path"]; let output = Command::new("cargo") @@ -207,41 +212,53 @@ fn add_crate_to_source_distribution( ); } if !output.stderr.is_empty() { - eprintln!("From `cargo {}`:", args.join(" ")); + eprintln!( + "From `cargo {} {}`:", + args.join(" "), + manifest_path.display() + ); std::io::stderr().write_all(&output.stderr)?; } - let file_list: Vec<&Path> = str::from_utf8(&output.stdout) + let file_list: Vec<&str> = str::from_utf8(&output.stdout) .context("Cargo printed invalid utf-8 ಠ_ಠ")? .lines() - .map(Path::new) .collect(); + trace!("File list: {}", file_list.join(", ")); + // manifest_dir should be a relative path let manifest_dir = manifest_path.parent().unwrap(); - let target_source: Vec<(PathBuf, PathBuf)> = file_list - .iter() + let target_source: Vec<_> = file_list + .into_iter() .map(|relative_to_manifests| { let relative_to_cwd = manifest_dir.join(relative_to_manifests); - (relative_to_manifests.to_path_buf(), relative_to_cwd) + (relative_to_manifests, relative_to_cwd) }) - // We rewrite Cargo.toml and add it separately .filter(|(target, source)| { #[allow(clippy::if_same_then_else)] - // Skip generated files. See https://github.com/rust-lang/cargo/issues/7938#issuecomment-593280660 - // and https://github.com/PyO3/maturin/issues/449 - if target == Path::new("Cargo.toml.orig") || target == Path::new("Cargo.toml") { + if *target == "Cargo.toml.orig" { + // Skip generated files. See https://github.com/rust-lang/cargo/issues/7938#issuecomment-593280660 + // and https://github.com/PyO3/maturin/issues/449 + false + } else if *target == "Cargo.toml" { + // We rewrite Cargo.toml and add it separately false - } else if root_crate && target == Path::new("pyproject.toml") { - // pyproject.toml is handled separately because it has be to put in the root dir + } else if root_crate && *target == "pyproject.toml" { + // pyproject.toml is handled separately because it has to be put in the root dir // of source distribution false - } else if matches!(target.extension(), Some(ext) if ext == "pyc" || ext == "pyd" || ext == "so") { + } else if prefix.components().count() == 1 && *target == "pyproject.toml" { + // Skip pyproject.toml for cases when the root is in a workspace member and both the + // member and the root have a pyproject.toml. + debug!("Skipping potentially non-main {}", prefix.join(target).display()); + false + } else if matches!(Path::new(target).extension(), Some(ext) if ext == "pyc" || ext == "pyd" || ext == "so") { // Technically, `cargo package --list` should handle this, // but somehow it doesn't on Alpine Linux running in GitHub Actions, // so we do it manually here. // See https://github.com/PyO3/maturin/pull/1255#issuecomment-1308838786 - debug!("Ignoring {}", target.display()); + debug!("Ignoring {}", target); false } else { source.exists() @@ -249,7 +266,6 @@ fn add_crate_to_source_distribution( }) .collect(); - let prefix = prefix.as_ref(); writer.add_directory(prefix)?; let cargo_toml_path = prefix.join(manifest_path.file_name().unwrap()); @@ -468,6 +484,7 @@ fn add_cargo_package_files_to_sdist( .with_context(|| format!("Failed to add path dependency {}", name))?; } + debug!("Adding the main crate {}", manifest_path.display()); // Add the main crate let abs_manifest_path = manifest_path .normalize() @@ -503,7 +520,12 @@ fn add_cargo_package_files_to_sdist( .into_path_buf(); // Add readme next to Cargo.toml so we don't get collisions between crates using readmes // higher up the file tree. - writer.add_file(root_dir.join(readme.file_name().unwrap()), &abs_readme)?; + writer.add_file( + root_dir + .join(relative_main_crate_manifest_dir) + .join(readme.file_name().unwrap()), + &abs_readme, + )?; } // Add Cargo.lock file and workspace Cargo.toml diff --git a/test-crates/workspace-inverted-order/Cargo.lock b/test-crates/workspace-inverted-order/Cargo.lock new file mode 100644 index 000000000..44c9c8b48 --- /dev/null +++ b/test-crates/workspace-inverted-order/Cargo.lock @@ -0,0 +1,176 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "indoc" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" + +[[package]] +name = "libc" +version = "0.2.161" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "path_dep_with_root" +version = "0.1.0" +dependencies = [ + "pyo3", + "top_level", +] + +[[package]] +name = "portable-atomic" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" + +[[package]] +name = "proc-macro2" +version = "1.0.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pyo3" +version = "0.22.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d922163ba1f79c04bc49073ba7b32fd5a8d3b76a87c955921234b8e77333c51" +dependencies = [ + "cfg-if", + "indoc", + "libc", + "memoffset", + "once_cell", + "portable-atomic", + "pyo3-build-config", + "pyo3-ffi", + "pyo3-macros", + "unindent", +] + +[[package]] +name = "pyo3-build-config" +version = "0.22.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc38c5feeb496c8321091edf3d63e9a6829eab4b863b4a6a65f26f3e9cc6b179" +dependencies = [ + "once_cell", + "target-lexicon", +] + +[[package]] +name = "pyo3-ffi" +version = "0.22.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94845622d88ae274d2729fcefc850e63d7a3ddff5e3ce11bd88486db9f1d357d" +dependencies = [ + "libc", + "pyo3-build-config", +] + +[[package]] +name = "pyo3-macros" +version = "0.22.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e655aad15e09b94ffdb3ce3d217acf652e26bbc37697ef012f5e5e348c716e5e" +dependencies = [ + "proc-macro2", + "pyo3-macros-backend", + "quote", + "syn", +] + +[[package]] +name = "pyo3-macros-backend" +version = "0.22.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1e3f09eecd94618f60a455a23def79f79eba4dc561a97324bf9ac8c6df30ce" +dependencies = [ + "heck", + "proc-macro2", + "pyo3-build-config", + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "top_level" +version = "0.1.0" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unindent" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" diff --git a/test-crates/workspace-inverted-order/Cargo.toml b/test-crates/workspace-inverted-order/Cargo.toml new file mode 100644 index 000000000..cd05d5706 --- /dev/null +++ b/test-crates/workspace-inverted-order/Cargo.toml @@ -0,0 +1,17 @@ +[workspace] +members = [ + ".", + "path-dep-with-root", +] + +[workspace.package] +authors = [] +version = "0.10.2-dev" +publish = false +repository = "https://github.com/mitmproxy/mitmproxy-rs" + +[package] +name = "top_level" +version = "0.1.0" +description = "root dep" +edition = "2021" diff --git a/test-crates/workspace-inverted-order/README.md b/test-crates/workspace-inverted-order/README.md new file mode 100644 index 000000000..68f7f5a03 --- /dev/null +++ b/test-crates/workspace-inverted-order/README.md @@ -0,0 +1,3 @@ +# Root readme + +In this workspace, the build root is in a subdirectory, while the workspace root also contains a crate. diff --git a/test-crates/workspace-inverted-order/check_installed/check_installed.py b/test-crates/workspace-inverted-order/check_installed/check_installed.py new file mode 100755 index 000000000..1c4a2f129 --- /dev/null +++ b/test-crates/workspace-inverted-order/check_installed/check_installed.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 +import path_dep_with_root + +assert path_dep_with_root.add_number(2) == 44 + +print("SUCCESS") diff --git a/test-crates/workspace-inverted-order/path-dep-with-root/Cargo.toml b/test-crates/workspace-inverted-order/path-dep-with-root/Cargo.toml new file mode 100644 index 000000000..08939762f --- /dev/null +++ b/test-crates/workspace-inverted-order/path-dep-with-root/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "path_dep_with_root" +version = "0.1.0" +description = "path dep" +edition = "2021" + +[lib] +name = "path_dep_with_root" +crate-type = ["lib", "cdylib"] + +[dependencies] +top_level = { path = "../" } +pyo3 = { version = "0.22.5", features = ["abi3", "abi3-py310", "extension-module"] } diff --git a/test-crates/workspace-inverted-order/path-dep-with-root/README.md b/test-crates/workspace-inverted-order/path-dep-with-root/README.md new file mode 100644 index 000000000..0dd4a9be1 --- /dev/null +++ b/test-crates/workspace-inverted-order/path-dep-with-root/README.md @@ -0,0 +1 @@ +# Path readme diff --git a/test-crates/workspace-inverted-order/path-dep-with-root/pyproject.toml b/test-crates/workspace-inverted-order/path-dep-with-root/pyproject.toml new file mode 100644 index 000000000..997f80bf9 --- /dev/null +++ b/test-crates/workspace-inverted-order/path-dep-with-root/pyproject.toml @@ -0,0 +1,8 @@ +[build-system] +requires = ["maturin>=1,<2"] +build-backend = "maturin" + +[project] +name = "mitmproxy_path" +version = "0.1.0" +requires-python = ">=3.10" diff --git a/test-crates/workspace-inverted-order/path-dep-with-root/src/lib.rs b/test-crates/workspace-inverted-order/path-dep-with-root/src/lib.rs new file mode 100644 index 000000000..31342a46b --- /dev/null +++ b/test-crates/workspace-inverted-order/path-dep-with-root/src/lib.rs @@ -0,0 +1,12 @@ +use pyo3::prelude::*; + +#[pymodule] +mod path_dep_with_root { + use pyo3::pyfunction; + use top_level::NUMBER; + + #[pyfunction] + fn add_number(x: u32) -> u32 { + x + NUMBER + } +} diff --git a/test-crates/workspace-inverted-order/pyproject.toml b/test-crates/workspace-inverted-order/pyproject.toml new file mode 100644 index 000000000..0fa885941 --- /dev/null +++ b/test-crates/workspace-inverted-order/pyproject.toml @@ -0,0 +1,2 @@ +[tool.dummy] +value = 1 diff --git a/test-crates/workspace-inverted-order/src/lib.rs b/test-crates/workspace-inverted-order/src/lib.rs new file mode 100755 index 000000000..2fefc8c7b --- /dev/null +++ b/test-crates/workspace-inverted-order/src/lib.rs @@ -0,0 +1 @@ +pub const NUMBER: u32 = 42; diff --git a/tests/run.rs b/tests/run.rs index adc5fa996..6b70ac93b 100644 --- a/tests/run.rs +++ b/tests/run.rs @@ -481,6 +481,17 @@ fn integration_readme_duplication() { )); } +#[test] +fn integration_workspace_inverted_order() { + handle_result(integration::test_integration( + "test-crates/workspace-inverted-order/path-dep-with-root", + None, + "integration-workspace-inverted-order", + false, + None, + )); +} + #[test] // Sourced from https://pypi.org/project/wasmtime/11.0.0/#files // update with wasmtime updates