Skip to content

Commit 91b042a

Browse files
authored
Merge pull request #720 from messense/workspace-path-dep
Don't package non-path-dep crates in sdist for workspaces
2 parents 9c849b6 + b7f18b4 commit 91b042a

File tree

16 files changed

+499
-29
lines changed

16 files changed

+499
-29
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## [Unreleased]
99

1010
* Add a `maturin init` command as a companion to `maturin new` in [#719](https://github.com/PyO3/maturin/pull/719)
11+
* Don't package non-path-dep crates in sdist for workspaces in [#720](https://github.com/PyO3/maturin/pull/720)
1112

1213
## [0.12.3] - 2021-11-29
1314

src/source_distribution.rs

Lines changed: 71 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::module_writer::ModuleWriter;
22
use crate::{Metadata21, SDistWriter};
33
use anyhow::{bail, Context, Result};
4-
use cargo_metadata::Metadata;
4+
use cargo_metadata::{Metadata, PackageId};
55
use fs_err as fs;
66
use std::collections::HashMap;
77
use std::path::{Path, PathBuf};
@@ -10,6 +10,12 @@ use std::str;
1010

1111
const LOCAL_DEPENDENCIES_FOLDER: &str = "local_dependencies";
1212

13+
#[derive(Debug, Clone)]
14+
struct PathDependency {
15+
id: PackageId,
16+
path: PathBuf,
17+
}
18+
1319
/// We need cargo to load the local dependencies from the location where we put them in the source
1420
/// distribution. Since there is no cargo-backed way to replace dependencies
1521
/// (see https://github.com/rust-lang/cargo/issues/9170), we do a simple
@@ -19,7 +25,7 @@ const LOCAL_DEPENDENCIES_FOLDER: &str = "local_dependencies";
1925
/// This method is rather frail, but unfortunately I don't know a better solution.
2026
fn rewrite_cargo_toml(
2127
manifest_path: impl AsRef<Path>,
22-
known_path_deps: &HashMap<String, PathBuf>,
28+
known_path_deps: &HashMap<String, PathDependency>,
2329
root_crate: bool,
2430
) -> Result<String> {
2531
let text = fs::read_to_string(&manifest_path).context(format!(
@@ -87,7 +93,7 @@ fn add_crate_to_source_distribution(
8793
writer: &mut SDistWriter,
8894
manifest_path: impl AsRef<Path>,
8995
prefix: impl AsRef<Path>,
90-
known_path_deps: &HashMap<String, PathBuf>,
96+
known_path_deps: &HashMap<String, PathDependency>,
9197
root_crate: bool,
9298
) -> Result<()> {
9399
let output = Command::new("cargo")
@@ -157,43 +163,80 @@ fn add_crate_to_source_distribution(
157163
Ok(())
158164
}
159165

160-
/// Creates aif source distribution, packing the root crate and all local dependencies
161-
///
162-
/// The source distribution format is specified in
163-
/// [PEP 517 under "build_sdist"](https://www.python.org/dev/peps/pep-0517/#build-sdist)
164-
/// and in
165-
/// https://packaging.python.org/specifications/source-distribution-format/#source-distribution-file-format
166-
pub fn source_distribution(
167-
wheel_dir: impl AsRef<Path>,
168-
metadata21: &Metadata21,
169-
manifest_path: impl AsRef<Path>,
166+
/// Get path dependencies for a cargo package
167+
fn get_path_deps(
170168
cargo_metadata: &Metadata,
171-
sdist_include: Option<&Vec<String>>,
172-
) -> Result<PathBuf> {
169+
resolve: &cargo_metadata::Resolve,
170+
pkg_id: &cargo_metadata::PackageId,
171+
visited: &HashMap<String, PathDependency>,
172+
) -> Result<HashMap<String, PathDependency>> {
173173
// Parse ids in the format:
174174
// on unix: some_path_dep 0.1.0 (path+file:///home/konsti/maturin/test-crates/some_path_dep)
175175
// on windows: some_path_dep 0.1.0 (path+file:///C:/konsti/maturin/test-crates/some_path_dep)
176176
// This is not a good way to identify path dependencies, but I don't know a better one
177-
let resolve = cargo_metadata
178-
.resolve
179-
.as_ref()
180-
.context("Expected to get a dependency graph from cargo")?;
181-
let known_path_deps: HashMap<String, PathBuf> = resolve
177+
let node = resolve
182178
.nodes
183179
.iter()
184-
.filter(|node| {
185-
&node.id != resolve.root.as_ref().unwrap() && node.id.repr.contains("path+file://")
186-
})
180+
.find(|node| &node.id == pkg_id)
181+
.context("Expected to get a node of dependency graph from cargo")?;
182+
let path_deps = node
183+
.deps
184+
.iter()
185+
.filter(|node| node.pkg.repr.contains("path+file://"))
187186
.filter_map(|node| {
188187
cargo_metadata.packages.iter().find_map(|pkg| {
189-
if pkg.id.repr == node.id.repr {
190-
Some((pkg.name.clone(), PathBuf::from(&pkg.manifest_path)))
188+
if pkg.id.repr == node.pkg.repr && !visited.contains_key(&pkg.name) {
189+
let path_dep = PathDependency {
190+
id: pkg.id.clone(),
191+
path: PathBuf::from(&pkg.manifest_path),
192+
};
193+
Some((pkg.name.clone(), path_dep))
191194
} else {
192195
None
193196
}
194197
})
195198
})
196199
.collect();
200+
Ok(path_deps)
201+
}
202+
203+
/// Finds all path dependencies of the crate
204+
fn find_path_deps(cargo_metadata: &Metadata) -> Result<HashMap<String, PathDependency>> {
205+
let resolve = cargo_metadata
206+
.resolve
207+
.as_ref()
208+
.context("Expected to get a dependency graph from cargo")?;
209+
let root = resolve
210+
.root
211+
.clone()
212+
.context("Expected to get a root package id of dependency graph from cargo")?;
213+
let mut known_path_deps = HashMap::new();
214+
let mut stack = vec![root];
215+
while let Some(pkg_id) = stack.pop() {
216+
let path_deps = get_path_deps(cargo_metadata, resolve, &pkg_id, &known_path_deps)?;
217+
if path_deps.is_empty() {
218+
continue;
219+
}
220+
stack.extend(path_deps.values().map(|dep| dep.id.clone()));
221+
known_path_deps.extend(path_deps);
222+
}
223+
Ok(known_path_deps)
224+
}
225+
226+
/// Creates a source distribution, packing the root crate and all local dependencies
227+
///
228+
/// The source distribution format is specified in
229+
/// [PEP 517 under "build_sdist"](https://www.python.org/dev/peps/pep-0517/#build-sdist)
230+
/// and in
231+
/// https://packaging.python.org/specifications/source-distribution-format/#source-distribution-file-format
232+
pub fn source_distribution(
233+
wheel_dir: impl AsRef<Path>,
234+
metadata21: &Metadata21,
235+
manifest_path: impl AsRef<Path>,
236+
cargo_metadata: &Metadata,
237+
sdist_include: Option<&Vec<String>>,
238+
) -> Result<PathBuf> {
239+
let known_path_deps = find_path_deps(cargo_metadata)?;
197240

198241
let mut writer = SDistWriter::new(wheel_dir, metadata21)?;
199242
let root_dir = PathBuf::from(format!(
@@ -203,18 +246,18 @@ pub fn source_distribution(
203246
));
204247

205248
// Add local path dependencies
206-
for (name, path) in known_path_deps.iter() {
249+
for (name, path_dep) in known_path_deps.iter() {
207250
add_crate_to_source_distribution(
208251
&mut writer,
209-
&path,
252+
&path_dep.path,
210253
&root_dir.join(LOCAL_DEPENDENCIES_FOLDER).join(name),
211254
&known_path_deps,
212255
false,
213256
)
214257
.context(format!(
215258
"Failed to add local dependency {} at {} to the source distribution",
216259
name,
217-
path.display()
260+
path_dep.path.display()
218261
))?;
219262
}
220263

0 commit comments

Comments
 (0)