1
1
use std:: collections:: { BTreeMap , BTreeSet , HashMap , HashSet } ;
2
2
use std:: fmt;
3
+ use std:: marker:: PhantomData ;
3
4
use std:: path:: { Path , PathBuf } ;
4
5
use std:: rc:: Rc ;
5
6
use std:: str;
@@ -22,7 +23,9 @@ use crate::core::{GitReference, PackageIdSpec, SourceId, WorkspaceConfig, Worksp
22
23
use crate :: sources:: { CRATES_IO_INDEX , CRATES_IO_REGISTRY } ;
23
24
use crate :: util:: errors:: { CargoResult , CargoResultExt , ManifestError } ;
24
25
use crate :: util:: interning:: InternedString ;
25
- use crate :: util:: { self , paths, validate_package_name, Config , IntoUrl } ;
26
+ use crate :: util:: {
27
+ self , config:: ConfigRelativePath , paths, validate_package_name, Config , IntoUrl ,
28
+ } ;
26
29
27
30
mod targets;
28
31
use self :: targets:: targets;
@@ -199,25 +202,25 @@ type TomlBenchTarget = TomlTarget;
199
202
200
203
#[ derive( Clone , Debug , Serialize ) ]
201
204
#[ serde( untagged) ]
202
- pub enum TomlDependency {
205
+ pub enum TomlDependency < P = String > {
203
206
/// In the simple format, only a version is specified, eg.
204
207
/// `package = "<version>"`
205
208
Simple ( String ) ,
206
209
/// The simple format is equivalent to a detailed dependency
207
210
/// specifying only a version, eg.
208
211
/// `package = { version = "<version>" }`
209
- Detailed ( DetailedTomlDependency ) ,
212
+ Detailed ( DetailedTomlDependency < P > ) ,
210
213
}
211
214
212
- impl < ' de > de:: Deserialize < ' de > for TomlDependency {
215
+ impl < ' de , P : Deserialize < ' de > > de:: Deserialize < ' de > for TomlDependency < P > {
213
216
fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
214
217
where
215
218
D : de:: Deserializer < ' de > ,
216
219
{
217
- struct TomlDependencyVisitor ;
220
+ struct TomlDependencyVisitor < P > ( PhantomData < P > ) ;
218
221
219
- impl < ' de > de:: Visitor < ' de > for TomlDependencyVisitor {
220
- type Value = TomlDependency ;
222
+ impl < ' de , P : Deserialize < ' de > > de:: Visitor < ' de > for TomlDependencyVisitor < P > {
223
+ type Value = TomlDependency < P > ;
221
224
222
225
fn expecting ( & self , formatter : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
223
226
formatter. write_str (
@@ -242,13 +245,29 @@ impl<'de> de::Deserialize<'de> for TomlDependency {
242
245
}
243
246
}
244
247
245
- deserializer. deserialize_any ( TomlDependencyVisitor )
248
+ deserializer. deserialize_any ( TomlDependencyVisitor ( PhantomData ) )
246
249
}
247
250
}
248
251
249
- #[ derive( Deserialize , Serialize , Clone , Debug , Default ) ]
252
+ pub trait ResolveToPath {
253
+ fn resolve ( & self , config : & Config ) -> PathBuf ;
254
+ }
255
+
256
+ impl ResolveToPath for String {
257
+ fn resolve ( & self , _: & Config ) -> PathBuf {
258
+ self . into ( )
259
+ }
260
+ }
261
+
262
+ impl ResolveToPath for ConfigRelativePath {
263
+ fn resolve ( & self , c : & Config ) -> PathBuf {
264
+ self . resolve_path ( c)
265
+ }
266
+ }
267
+
268
+ #[ derive( Deserialize , Serialize , Clone , Debug ) ]
250
269
#[ serde( rename_all = "kebab-case" ) ]
251
- pub struct DetailedTomlDependency {
270
+ pub struct DetailedTomlDependency < P = String > {
252
271
version : Option < String > ,
253
272
registry : Option < String > ,
254
273
/// The URL of the `registry` field.
@@ -258,7 +277,9 @@ pub struct DetailedTomlDependency {
258
277
/// registry names configured, so Cargo can't rely on just the name for
259
278
/// crates published by other users.
260
279
registry_index : Option < String > ,
261
- path : Option < String > ,
280
+ // `path` is relative to the file it appears in. If that's a `Cargo.toml`, it'll be relative to
281
+ // that TOML file, and if it's a `.cargo/config` file, it'll be relative to that file.
282
+ path : Option < P > ,
262
283
git : Option < String > ,
263
284
branch : Option < String > ,
264
285
tag : Option < String > ,
@@ -272,6 +293,28 @@ pub struct DetailedTomlDependency {
272
293
public : Option < bool > ,
273
294
}
274
295
296
+ // Explicit implementation so we avoid pulling in P: Default
297
+ impl < P > Default for DetailedTomlDependency < P > {
298
+ fn default ( ) -> Self {
299
+ Self {
300
+ version : Default :: default ( ) ,
301
+ registry : Default :: default ( ) ,
302
+ registry_index : Default :: default ( ) ,
303
+ path : Default :: default ( ) ,
304
+ git : Default :: default ( ) ,
305
+ branch : Default :: default ( ) ,
306
+ tag : Default :: default ( ) ,
307
+ rev : Default :: default ( ) ,
308
+ features : Default :: default ( ) ,
309
+ optional : Default :: default ( ) ,
310
+ default_features : Default :: default ( ) ,
311
+ default_features2 : Default :: default ( ) ,
312
+ package : Default :: default ( ) ,
313
+ public : Default :: default ( ) ,
314
+ }
315
+ }
316
+ }
317
+
275
318
/// This type is used to deserialize `Cargo.toml` files.
276
319
#[ derive( Debug , Deserialize , Serialize ) ]
277
320
#[ serde( rename_all = "kebab-case" ) ]
@@ -1627,15 +1670,45 @@ fn unique_build_targets(targets: &[Target], package_root: &Path) -> Result<(), S
1627
1670
Ok ( ( ) )
1628
1671
}
1629
1672
1630
- impl TomlDependency {
1673
+ impl < P : ResolveToPath > TomlDependency < P > {
1674
+ pub ( crate ) fn to_dependency_split (
1675
+ & self ,
1676
+ name : & str ,
1677
+ pkgid : Option < PackageId > ,
1678
+ source_id : SourceId ,
1679
+ nested_paths : & mut Vec < PathBuf > ,
1680
+ config : & Config ,
1681
+ warnings : & mut Vec < String > ,
1682
+ platform : Option < Platform > ,
1683
+ root : & Path ,
1684
+ features : & Features ,
1685
+ kind : Option < DepKind > ,
1686
+ ) -> CargoResult < Dependency > {
1687
+ self . to_dependency (
1688
+ name,
1689
+ & mut Context {
1690
+ pkgid,
1691
+ deps : & mut Vec :: new ( ) ,
1692
+ source_id,
1693
+ nested_paths,
1694
+ config,
1695
+ warnings,
1696
+ platform,
1697
+ root,
1698
+ features,
1699
+ } ,
1700
+ kind,
1701
+ )
1702
+ }
1703
+
1631
1704
fn to_dependency (
1632
1705
& self ,
1633
1706
name : & str ,
1634
1707
cx : & mut Context < ' _ , ' _ > ,
1635
1708
kind : Option < DepKind > ,
1636
1709
) -> CargoResult < Dependency > {
1637
1710
match * self {
1638
- TomlDependency :: Simple ( ref version) => DetailedTomlDependency {
1711
+ TomlDependency :: Simple ( ref version) => DetailedTomlDependency :: < P > {
1639
1712
version : Some ( version. clone ( ) ) ,
1640
1713
..Default :: default ( )
1641
1714
}
@@ -1652,7 +1725,7 @@ impl TomlDependency {
1652
1725
}
1653
1726
}
1654
1727
1655
- impl DetailedTomlDependency {
1728
+ impl < P : ResolveToPath > DetailedTomlDependency < P > {
1656
1729
fn to_dependency (
1657
1730
& self ,
1658
1731
name_in_toml : & str ,
@@ -1762,7 +1835,8 @@ impl DetailedTomlDependency {
1762
1835
SourceId :: for_git ( & loc, reference) ?
1763
1836
}
1764
1837
( None , Some ( path) , _, _) => {
1765
- cx. nested_paths . push ( PathBuf :: from ( path) ) ;
1838
+ let path = path. resolve ( cx. config ) ;
1839
+ cx. nested_paths . push ( path. clone ( ) ) ;
1766
1840
// If the source ID for the package we're parsing is a path
1767
1841
// source, then we normalize the path here to get rid of
1768
1842
// components like `..`.
0 commit comments