Skip to content

Commit b36cc6e

Browse files
committed
Auto merge of #10538 - Muscraft:rfc2906-part3, r=epage
Part 3 of RFC2906 - Add support for inheriting `license-path`, and `depednency.path` Tracking issue: #8415 RFC: rust-lang/rfcs#2906 [Part 1](#10497) [Part 2](#10517) This PR focuses on adding support for inheriting `license-path`, and `depednency.path`: - To adjust the relative paths from being workspace-relative to package-relative, we use `pathdiff` which `cargo-add` is also going to be using for a similar purpose - `ws_path` was added to `InheritableFields` so we can resolve relative paths from workspace-relative to package-relative - Moved `resolve` for toml dependencies from `TomlDependency::<P>` to `TomlDependency` - This was done since resolving a relative path should be a string - You should never inherit from a `.cargo/config.toml` which is the reason `P` was added Remaining implementation work for the RFC - Relative paths for `readme` - Path dependencies infer version directive - Lock workspace dependencies and warn when unused - Optimizations, as needed - Evaluate any new fields for being inheritable (e.g. `rust-version`)
2 parents ede7875 + 3d07652 commit b36cc6e

File tree

5 files changed

+165
-23
lines changed

5 files changed

+165
-23
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ libgit2-sys = "0.13.2"
4545
memchr = "2.1.3"
4646
opener = "0.5"
4747
os_info = "3.0.7"
48+
pathdiff = "0.2.1"
4849
percent-encoding = "2.0"
4950
rustfix = "0.6.0"
5051
semver = { version = "1.0.3", features = ["serde"] }

src/cargo/core/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ pub use self::shell::{Shell, Verbosity};
1111
pub use self::source::{GitReference, Source, SourceId, SourceMap};
1212
pub use self::summary::{FeatureMap, FeatureValue, Summary};
1313
pub use self::workspace::{
14-
find_workspace_root, InheritableFields, MaybePackage, Workspace, WorkspaceConfig,
15-
WorkspaceRootConfig,
14+
find_workspace_root, resolve_relative_path, InheritableFields, MaybePackage, Workspace,
15+
WorkspaceConfig, WorkspaceRootConfig,
1616
};
1717

1818
pub mod compiler;

src/cargo/core/workspace.rs

+38-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ use crate::util::toml::{
2727
};
2828
use crate::util::{config::ConfigRelativePath, Config, Filesystem, IntoUrl};
2929
use cargo_util::paths;
30+
use cargo_util::paths::normalize_path;
31+
use pathdiff::diff_paths;
3032

3133
/// The core abstraction in Cargo for working with a workspace of crates.
3234
///
@@ -1650,6 +1652,7 @@ pub struct InheritableFields {
16501652
publish: Option<VecStringOrBool>,
16511653
edition: Option<String>,
16521654
badges: Option<BTreeMap<String, BTreeMap<String, String>>>,
1655+
ws_root: PathBuf,
16531656
}
16541657

16551658
impl InheritableFields {
@@ -1669,6 +1672,7 @@ impl InheritableFields {
16691672
publish: Option<VecStringOrBool>,
16701673
edition: Option<String>,
16711674
badges: Option<BTreeMap<String, BTreeMap<String, String>>>,
1675+
ws_root: PathBuf,
16721676
) -> InheritableFields {
16731677
Self {
16741678
dependencies,
@@ -1686,6 +1690,7 @@ impl InheritableFields {
16861690
publish,
16871691
edition,
16881692
badges,
1693+
ws_root,
16891694
}
16901695
}
16911696

@@ -1780,10 +1785,10 @@ impl InheritableFields {
17801785
})
17811786
}
17821787

1783-
pub fn license_file(&self) -> CargoResult<String> {
1788+
pub fn license_file(&self, package_root: &Path) -> CargoResult<String> {
17841789
self.license_file.clone().map_or(
17851790
Err(anyhow!("`workspace.license_file` was not defined")),
1786-
|d| Ok(d),
1791+
|d| resolve_relative_path("license-file", &self.ws_root, package_root, &d),
17871792
)
17881793
}
17891794

@@ -1817,6 +1822,37 @@ impl InheritableFields {
18171822
Ok(d)
18181823
})
18191824
}
1825+
1826+
pub fn ws_root(&self) -> &PathBuf {
1827+
&self.ws_root
1828+
}
1829+
}
1830+
1831+
pub fn resolve_relative_path(
1832+
label: &str,
1833+
old_root: &Path,
1834+
new_root: &Path,
1835+
rel_path: &str,
1836+
) -> CargoResult<String> {
1837+
let joined_path = normalize_path(&old_root.join(rel_path));
1838+
match diff_paths(joined_path, new_root) {
1839+
None => Err(anyhow!(
1840+
"`{}` was defined in {} but could not be resolved with {}",
1841+
label,
1842+
old_root.display(),
1843+
new_root.display()
1844+
)),
1845+
Some(path) => Ok(path
1846+
.to_str()
1847+
.ok_or_else(|| {
1848+
anyhow!(
1849+
"`{}` resolved to non-UTF value (`{}`)",
1850+
label,
1851+
path.display()
1852+
)
1853+
})?
1854+
.to_owned()),
1855+
}
18201856
}
18211857

18221858
fn parse_manifest(manifest_path: &Path, config: &Config) -> CargoResult<EitherManifest> {

src/cargo/util/toml/mod.rs

+65-16
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ use crate::core::compiler::{CompileKind, CompileTarget};
2020
use crate::core::dependency::{Artifact, ArtifactTarget, DepKind};
2121
use crate::core::manifest::{ManifestMetadata, TargetSourcePath, Warnings};
2222
use crate::core::resolver::ResolveBehavior;
23-
use crate::core::{find_workspace_root, Dependency, Manifest, PackageId, Summary, Target};
23+
use crate::core::{
24+
find_workspace_root, resolve_relative_path, Dependency, Manifest, PackageId, Summary, Target,
25+
};
2426
use crate::core::{
2527
Edition, EitherManifest, Feature, Features, InheritableFields, VirtualManifest, Workspace,
2628
};
@@ -1021,6 +1023,12 @@ impl<T> MaybeWorkspace<T> {
10211023
)),
10221024
}
10231025
}
1026+
fn as_defined(&self) -> Option<&T> {
1027+
match self {
1028+
MaybeWorkspace::Workspace(_) => None,
1029+
MaybeWorkspace::Defined(defined) => Some(defined),
1030+
}
1031+
}
10241032
}
10251033

10261034
#[derive(Deserialize, Serialize, Clone, Debug)]
@@ -1069,7 +1077,7 @@ pub struct TomlProject {
10691077
keywords: Option<MaybeWorkspace<Vec<String>>>,
10701078
categories: Option<MaybeWorkspace<Vec<String>>>,
10711079
license: Option<MaybeWorkspace<String>>,
1072-
license_file: Option<String>,
1080+
license_file: Option<MaybeWorkspace<String>>,
10731081
repository: Option<MaybeWorkspace<String>>,
10741082
resolver: Option<String>,
10751083

@@ -1149,19 +1157,22 @@ impl TomlManifest {
11491157
package.workspace = None;
11501158
package.resolver = ws.resolve_behavior().to_manifest();
11511159
if let Some(license_file) = &package.license_file {
1160+
let license_file = license_file
1161+
.as_defined()
1162+
.context("license file should have been resolved before `prepare_for_publish()`")?;
11521163
let license_path = Path::new(&license_file);
11531164
let abs_license_path = paths::normalize_path(&package_root.join(license_path));
11541165
if abs_license_path.strip_prefix(package_root).is_err() {
11551166
// This path points outside of the package root. `cargo package`
11561167
// will copy it into the root, so adjust the path to this location.
1157-
package.license_file = Some(
1168+
package.license_file = Some(MaybeWorkspace::Defined(
11581169
license_path
11591170
.file_name()
11601171
.unwrap()
11611172
.to_str()
11621173
.unwrap()
11631174
.to_string(),
1164-
);
1175+
));
11651176
}
11661177
}
11671178
let all = |_d: &TomlDependency| true;
@@ -1340,6 +1351,7 @@ impl TomlManifest {
13401351
config.publish.clone(),
13411352
config.edition.clone(),
13421353
config.badges.clone(),
1354+
package_root.to_path_buf(),
13431355
);
13441356

13451357
WorkspaceConfig::Root(WorkspaceRootConfig::new(
@@ -1506,13 +1518,12 @@ impl TomlManifest {
15061518
};
15071519
let mut deps: BTreeMap<String, TomlDependency> = BTreeMap::new();
15081520
for (n, v) in dependencies.iter() {
1509-
let resolved = v.clone().resolve(features, n, || {
1521+
let resolved = v.clone().resolve(features, n, cx, || {
15101522
get_ws(
15111523
cx.config,
15121524
cx.root.join("Cargo.toml"),
15131525
workspace_config.clone(),
1514-
)?
1515-
.get_dependency(n)
1526+
)
15161527
})?;
15171528
let dep = resolved.to_dependency(n, cx, kind)?;
15181529
validate_package_name(dep.name_in_toml().as_str(), "dependency name", "")?;
@@ -1702,7 +1713,16 @@ impl TomlManifest {
17021713
})
17031714
})
17041715
.transpose()?,
1705-
license_file: project.license_file.clone(),
1716+
license_file: project
1717+
.license_file
1718+
.clone()
1719+
.map(|mw| {
1720+
mw.resolve(&features, "license", || {
1721+
get_ws(config, resolved_path.clone(), workspace_config.clone())?
1722+
.license_file(package_root)
1723+
})
1724+
})
1725+
.transpose()?,
17061726
repository: project
17071727
.repository
17081728
.clone()
@@ -1766,6 +1786,10 @@ impl TomlManifest {
17661786
.license
17671787
.clone()
17681788
.map(|license| MaybeWorkspace::Defined(license));
1789+
project.license_file = metadata
1790+
.license_file
1791+
.clone()
1792+
.map(|license_file| MaybeWorkspace::Defined(license_file));
17691793
project.repository = metadata
17701794
.repository
17711795
.clone()
@@ -1999,6 +2023,7 @@ impl TomlManifest {
19992023
config.publish.clone(),
20002024
config.edition.clone(),
20012025
config.badges.clone(),
2026+
root.to_path_buf(),
20022027
);
20032028
WorkspaceConfig::Root(WorkspaceRootConfig::new(
20042029
root,
@@ -2240,13 +2265,16 @@ impl<P: ResolveToPath + Clone> TomlDependency<P> {
22402265
TomlDependency::Workspace(w) => w.optional.unwrap_or(false),
22412266
}
22422267
}
2268+
}
22432269

2270+
impl TomlDependency {
22442271
fn resolve<'a>(
22452272
self,
22462273
cargo_features: &Features,
22472274
label: &str,
2248-
get_ws_dependency: impl FnOnce() -> CargoResult<TomlDependency<P>>,
2249-
) -> CargoResult<TomlDependency<P>> {
2275+
cx: &mut Context<'_, '_>,
2276+
get_inheritable: impl FnOnce() -> CargoResult<InheritableFields>,
2277+
) -> CargoResult<TomlDependency> {
22502278
match self {
22512279
TomlDependency::Detailed(d) => Ok(TomlDependency::Detailed(d)),
22522280
TomlDependency::Simple(s) => Ok(TomlDependency::Simple(s)),
@@ -2256,28 +2284,30 @@ impl<P: ResolveToPath + Clone> TomlDependency<P> {
22562284
optional,
22572285
}) => {
22582286
cargo_features.require(Feature::workspace_inheritance())?;
2259-
get_ws_dependency().context(format!(
2287+
let inheritable = get_inheritable()?;
2288+
inheritable.get_dependency(label).context(format!(
22602289
"error reading `dependencies.{}` from workspace root manifest's `workspace.dependencies.{}`",
22612290
label, label
22622291
)).map(|dep| {
22632292
match dep {
22642293
TomlDependency::Simple(s) => {
22652294
if optional.is_some() || features.is_some() {
2266-
TomlDependency::Detailed(DetailedTomlDependency::<P> {
2295+
Ok(TomlDependency::Detailed(DetailedTomlDependency {
22672296
version: Some(s),
22682297
optional,
22692298
features,
22702299
..Default::default()
2271-
})
2300+
}))
22722301
} else {
2273-
TomlDependency::Simple(s)
2302+
Ok(TomlDependency::Simple(s))
22742303
}
22752304
},
22762305
TomlDependency::Detailed(d) => {
22772306
let mut dep = d.clone();
22782307
dep.add_features(features);
22792308
dep.update_optional(optional);
2280-
TomlDependency::Detailed(dep)
2309+
dep.resolve_path(label,inheritable.ws_root(), cx.root)?;
2310+
Ok(TomlDependency::Detailed(dep))
22812311
},
22822312
TomlDependency::Workspace(_) => {
22832313
unreachable!(
@@ -2288,7 +2318,7 @@ impl<P: ResolveToPath + Clone> TomlDependency<P> {
22882318
)
22892319
},
22902320
}
2291-
})
2321+
})?
22922322
}
22932323
TomlDependency::Workspace(TomlWorkspaceDependency {
22942324
workspace: false, ..
@@ -2543,7 +2573,9 @@ impl<P: ResolveToPath + Clone> DetailedTomlDependency<P> {
25432573
}
25442574
Ok(dep)
25452575
}
2576+
}
25462577

2578+
impl DetailedTomlDependency {
25472579
fn add_features(&mut self, features: Option<Vec<String>>) {
25482580
self.features = match (self.features.clone(), features.clone()) {
25492581
(Some(dep_feat), Some(inherit_feat)) => Some(
@@ -2561,6 +2593,23 @@ impl<P: ResolveToPath + Clone> DetailedTomlDependency<P> {
25612593
fn update_optional(&mut self, optional: Option<bool>) {
25622594
self.optional = optional;
25632595
}
2596+
2597+
fn resolve_path(
2598+
&mut self,
2599+
name: &str,
2600+
root_path: &Path,
2601+
package_root: &Path,
2602+
) -> CargoResult<()> {
2603+
if let Some(rel_path) = &self.path {
2604+
self.path = Some(resolve_relative_path(
2605+
name,
2606+
root_path,
2607+
package_root,
2608+
rel_path,
2609+
)?)
2610+
}
2611+
Ok(())
2612+
}
25642613
}
25652614

25662615
#[derive(Default, Serialize, Deserialize, Debug, Clone)]

0 commit comments

Comments
 (0)