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