1
1
use crate :: module_writer:: ModuleWriter ;
2
2
use crate :: { Metadata21 , SDistWriter } ;
3
3
use anyhow:: { bail, Context , Result } ;
4
- use cargo_metadata:: Metadata ;
4
+ use cargo_metadata:: { Metadata , PackageId } ;
5
5
use fs_err as fs;
6
6
use std:: collections:: HashMap ;
7
7
use std:: path:: { Path , PathBuf } ;
@@ -10,6 +10,12 @@ use std::str;
10
10
11
11
const LOCAL_DEPENDENCIES_FOLDER : & str = "local_dependencies" ;
12
12
13
+ #[ derive( Debug , Clone ) ]
14
+ struct PathDependency {
15
+ id : PackageId ,
16
+ path : PathBuf ,
17
+ }
18
+
13
19
/// We need cargo to load the local dependencies from the location where we put them in the source
14
20
/// distribution. Since there is no cargo-backed way to replace dependencies
15
21
/// (see https://github.com/rust-lang/cargo/issues/9170), we do a simple
@@ -19,7 +25,7 @@ const LOCAL_DEPENDENCIES_FOLDER: &str = "local_dependencies";
19
25
/// This method is rather frail, but unfortunately I don't know a better solution.
20
26
fn rewrite_cargo_toml (
21
27
manifest_path : impl AsRef < Path > ,
22
- known_path_deps : & HashMap < String , PathBuf > ,
28
+ known_path_deps : & HashMap < String , PathDependency > ,
23
29
root_crate : bool ,
24
30
) -> Result < String > {
25
31
let text = fs:: read_to_string ( & manifest_path) . context ( format ! (
@@ -87,7 +93,7 @@ fn add_crate_to_source_distribution(
87
93
writer : & mut SDistWriter ,
88
94
manifest_path : impl AsRef < Path > ,
89
95
prefix : impl AsRef < Path > ,
90
- known_path_deps : & HashMap < String , PathBuf > ,
96
+ known_path_deps : & HashMap < String , PathDependency > ,
91
97
root_crate : bool ,
92
98
) -> Result < ( ) > {
93
99
let output = Command :: new ( "cargo" )
@@ -157,7 +163,44 @@ fn add_crate_to_source_distribution(
157
163
Ok ( ( ) )
158
164
}
159
165
160
- /// Creates aif source distribution, packing the root crate and all local dependencies
166
+ /// Get path dependencies for a cargo package
167
+ fn get_path_deps (
168
+ cargo_metadata : & Metadata ,
169
+ resolve : & cargo_metadata:: Resolve ,
170
+ pkg_id : & cargo_metadata:: PackageId ,
171
+ visited : & HashMap < String , PathDependency > ,
172
+ ) -> Result < HashMap < String , PathDependency > > {
173
+ // Parse ids in the format:
174
+ // on unix: some_path_dep 0.1.0 (path+file:///home/konsti/maturin/test-crates/some_path_dep)
175
+ // on windows: some_path_dep 0.1.0 (path+file:///C:/konsti/maturin/test-crates/some_path_dep)
176
+ // This is not a good way to identify path dependencies, but I don't know a better one
177
+ let node = resolve
178
+ . nodes
179
+ . iter ( )
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://" ) )
186
+ . filter_map ( |node| {
187
+ cargo_metadata. packages . iter ( ) . find_map ( |pkg| {
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) )
194
+ } else {
195
+ None
196
+ }
197
+ } )
198
+ } )
199
+ . collect ( ) ;
200
+ Ok ( path_deps)
201
+ }
202
+
203
+ /// Creates a source distribution, packing the root crate and all local dependencies
161
204
///
162
205
/// The source distribution format is specified in
163
206
/// [PEP 517 under "build_sdist"](https://www.python.org/dev/peps/pep-0517/#build-sdist)
@@ -170,37 +213,24 @@ pub fn source_distribution(
170
213
cargo_metadata : & Metadata ,
171
214
sdist_include : Option < & Vec < String > > ,
172
215
) -> Result < PathBuf > {
173
- // Parse ids in the format:
174
- // on unix: some_path_dep 0.1.0 (path+file:///home/konsti/maturin/test-crates/some_path_dep)
175
- // on windows: some_path_dep 0.1.0 (path+file:///C:/konsti/maturin/test-crates/some_path_dep)
176
- // This is not a good way to identify path dependencies, but I don't know a better one
177
216
let resolve = cargo_metadata
178
217
. resolve
179
218
. as_ref ( )
180
219
. context ( "Expected to get a dependency graph from cargo" ) ?;
181
220
let root = resolve
182
221
. root
183
- . as_ref ( )
222
+ . clone ( )
184
223
. context ( "Expected to get a root package id of dependency graph from cargo" ) ?;
185
- let root_node = resolve
186
- . nodes
187
- . iter ( )
188
- . find ( |node| & node. id == root)
189
- . context ( "Expected to get a root node of dependency graph from cargo" ) ?;
190
- let known_path_deps: HashMap < String , PathBuf > = root_node
191
- . deps
192
- . iter ( )
193
- . filter ( |node| node. pkg . repr . contains ( "path+file://" ) )
194
- . filter_map ( |node| {
195
- cargo_metadata. packages . iter ( ) . find_map ( |pkg| {
196
- if pkg. id . repr == node. pkg . repr {
197
- Some ( ( pkg. name . clone ( ) , PathBuf :: from ( & pkg. manifest_path ) ) )
198
- } else {
199
- None
200
- }
201
- } )
202
- } )
203
- . collect ( ) ;
224
+ let mut known_path_deps = HashMap :: new ( ) ;
225
+ let mut stack = vec ! [ root] ;
226
+ while let Some ( pkg_id) = stack. pop ( ) {
227
+ let path_deps = get_path_deps ( cargo_metadata, resolve, & pkg_id, & known_path_deps) ?;
228
+ if path_deps. is_empty ( ) {
229
+ continue ;
230
+ }
231
+ stack. extend ( path_deps. values ( ) . map ( |dep| dep. id . clone ( ) ) ) ;
232
+ known_path_deps. extend ( path_deps) ;
233
+ }
204
234
205
235
let mut writer = SDistWriter :: new ( wheel_dir, metadata21) ?;
206
236
let root_dir = PathBuf :: from ( format ! (
@@ -210,18 +240,18 @@ pub fn source_distribution(
210
240
) ) ;
211
241
212
242
// Add local path dependencies
213
- for ( name, path ) in known_path_deps. iter ( ) {
243
+ for ( name, path_dep ) in known_path_deps. iter ( ) {
214
244
add_crate_to_source_distribution (
215
245
& mut writer,
216
- & path,
246
+ & path_dep . path ,
217
247
& root_dir. join ( LOCAL_DEPENDENCIES_FOLDER ) . join ( name) ,
218
248
& known_path_deps,
219
249
false ,
220
250
)
221
251
. context ( format ! (
222
252
"Failed to add local dependency {} at {} to the source distribution" ,
223
253
name,
224
- path. display( )
254
+ path_dep . path. display( )
225
255
) ) ?;
226
256
}
227
257
0 commit comments