Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Part 3 of RFC2906 - Add support for inheriting license-path, and depednency.path #10538

Merged
merged 1 commit into from
Apr 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ libgit2-sys = "0.13.2"
memchr = "2.1.3"
opener = "0.5"
os_info = "3.0.7"
pathdiff = "0.2.1"
percent-encoding = "2.0"
rustfix = "0.6.0"
semver = { version = "1.0.3", features = ["serde"] }
Expand Down
4 changes: 2 additions & 2 deletions src/cargo/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ pub use self::shell::{Shell, Verbosity};
pub use self::source::{GitReference, Source, SourceId, SourceMap};
pub use self::summary::{FeatureMap, FeatureValue, Summary};
pub use self::workspace::{
find_workspace_root, InheritableFields, MaybePackage, Workspace, WorkspaceConfig,
WorkspaceRootConfig,
find_workspace_root, resolve_relative_path, InheritableFields, MaybePackage, Workspace,
WorkspaceConfig, WorkspaceRootConfig,
};

pub mod compiler;
Expand Down
40 changes: 38 additions & 2 deletions src/cargo/core/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ use crate::util::toml::{
};
use crate::util::{config::ConfigRelativePath, Config, Filesystem, IntoUrl};
use cargo_util::paths;
use cargo_util::paths::normalize_path;
use pathdiff::diff_paths;

/// The core abstraction in Cargo for working with a workspace of crates.
///
Expand Down Expand Up @@ -1650,6 +1652,7 @@ pub struct InheritableFields {
publish: Option<VecStringOrBool>,
edition: Option<String>,
badges: Option<BTreeMap<String, BTreeMap<String, String>>>,
ws_root: PathBuf,
}

impl InheritableFields {
Expand All @@ -1669,6 +1672,7 @@ impl InheritableFields {
publish: Option<VecStringOrBool>,
edition: Option<String>,
badges: Option<BTreeMap<String, BTreeMap<String, String>>>,
ws_root: PathBuf,
) -> InheritableFields {
Self {
dependencies,
Expand All @@ -1686,6 +1690,7 @@ impl InheritableFields {
publish,
edition,
badges,
ws_root,
}
}

Expand Down Expand Up @@ -1780,10 +1785,10 @@ impl InheritableFields {
})
}

pub fn license_file(&self) -> CargoResult<String> {
pub fn license_file(&self, package_root: &Path) -> CargoResult<String> {
self.license_file.clone().map_or(
Err(anyhow!("`workspace.license_file` was not defined")),
|d| Ok(d),
|d| resolve_relative_path("license-file", &self.ws_root, package_root, &d),
)
}

Expand Down Expand Up @@ -1817,6 +1822,37 @@ impl InheritableFields {
Ok(d)
})
}

pub fn ws_root(&self) -> &PathBuf {
&self.ws_root
}
}

pub fn resolve_relative_path(
label: &str,
old_root: &Path,
new_root: &Path,
rel_path: &str,
) -> CargoResult<String> {
let joined_path = normalize_path(&old_root.join(rel_path));
match diff_paths(joined_path, new_root) {
None => Err(anyhow!(
"`{}` was defined in {} but could not be resolved with {}",
label,
old_root.display(),
new_root.display()
)),
Some(path) => Ok(path
.to_str()
.ok_or_else(|| {
anyhow!(
"`{}` resolved to non-UTF value (`{}`)",
label,
path.display()
)
})?
.to_owned()),
}
}

fn parse_manifest(manifest_path: &Path, config: &Config) -> CargoResult<EitherManifest> {
Expand Down
81 changes: 65 additions & 16 deletions src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ use crate::core::compiler::{CompileKind, CompileTarget};
use crate::core::dependency::{Artifact, ArtifactTarget, DepKind};
use crate::core::manifest::{ManifestMetadata, TargetSourcePath, Warnings};
use crate::core::resolver::ResolveBehavior;
use crate::core::{find_workspace_root, Dependency, Manifest, PackageId, Summary, Target};
use crate::core::{
find_workspace_root, resolve_relative_path, Dependency, Manifest, PackageId, Summary, Target,
};
use crate::core::{
Edition, EitherManifest, Feature, Features, InheritableFields, VirtualManifest, Workspace,
};
Expand Down Expand Up @@ -1021,6 +1023,12 @@ impl<T> MaybeWorkspace<T> {
)),
}
}
fn as_defined(&self) -> Option<&T> {
match self {
MaybeWorkspace::Workspace(_) => None,
MaybeWorkspace::Defined(defined) => Some(defined),
}
}
}

#[derive(Deserialize, Serialize, Clone, Debug)]
Expand Down Expand Up @@ -1069,7 +1077,7 @@ pub struct TomlProject {
keywords: Option<MaybeWorkspace<Vec<String>>>,
categories: Option<MaybeWorkspace<Vec<String>>>,
license: Option<MaybeWorkspace<String>>,
license_file: Option<String>,
license_file: Option<MaybeWorkspace<String>>,
repository: Option<MaybeWorkspace<String>>,
resolver: Option<String>,

Expand Down Expand Up @@ -1149,19 +1157,22 @@ impl TomlManifest {
package.workspace = None;
package.resolver = ws.resolve_behavior().to_manifest();
if let Some(license_file) = &package.license_file {
let license_file = license_file
.as_defined()
.context("license file should have been resolved before `prepare_for_publish()`")?;
let license_path = Path::new(&license_file);
let abs_license_path = paths::normalize_path(&package_root.join(license_path));
if abs_license_path.strip_prefix(package_root).is_err() {
// This path points outside of the package root. `cargo package`
// will copy it into the root, so adjust the path to this location.
package.license_file = Some(
package.license_file = Some(MaybeWorkspace::Defined(
license_path
.file_name()
.unwrap()
.to_str()
.unwrap()
.to_string(),
);
));
}
}
let all = |_d: &TomlDependency| true;
Expand Down Expand Up @@ -1340,6 +1351,7 @@ impl TomlManifest {
config.publish.clone(),
config.edition.clone(),
config.badges.clone(),
package_root.to_path_buf(),
);

WorkspaceConfig::Root(WorkspaceRootConfig::new(
Expand Down Expand Up @@ -1506,13 +1518,12 @@ impl TomlManifest {
};
let mut deps: BTreeMap<String, TomlDependency> = BTreeMap::new();
for (n, v) in dependencies.iter() {
let resolved = v.clone().resolve(features, n, || {
let resolved = v.clone().resolve(features, n, cx, || {
get_ws(
cx.config,
cx.root.join("Cargo.toml"),
workspace_config.clone(),
)?
.get_dependency(n)
)
})?;
let dep = resolved.to_dependency(n, cx, kind)?;
validate_package_name(dep.name_in_toml().as_str(), "dependency name", "")?;
Expand Down Expand Up @@ -1702,7 +1713,16 @@ impl TomlManifest {
})
})
.transpose()?,
license_file: project.license_file.clone(),
license_file: project
.license_file
.clone()
.map(|mw| {
mw.resolve(&features, "license", || {
get_ws(config, resolved_path.clone(), workspace_config.clone())?
.license_file(package_root)
})
})
.transpose()?,
repository: project
.repository
.clone()
Expand Down Expand Up @@ -1766,6 +1786,10 @@ impl TomlManifest {
.license
.clone()
.map(|license| MaybeWorkspace::Defined(license));
project.license_file = metadata
.license_file
.clone()
.map(|license_file| MaybeWorkspace::Defined(license_file));
project.repository = metadata
.repository
.clone()
Expand Down Expand Up @@ -1999,6 +2023,7 @@ impl TomlManifest {
config.publish.clone(),
config.edition.clone(),
config.badges.clone(),
root.to_path_buf(),
);
WorkspaceConfig::Root(WorkspaceRootConfig::new(
root,
Expand Down Expand Up @@ -2240,13 +2265,16 @@ impl<P: ResolveToPath + Clone> TomlDependency<P> {
TomlDependency::Workspace(w) => w.optional.unwrap_or(false),
}
}
}

impl TomlDependency {
Comment on lines +2268 to +2270
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the new block?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same reasons as for DetailedTomlDependency

fn resolve<'a>(
self,
cargo_features: &Features,
label: &str,
get_ws_dependency: impl FnOnce() -> CargoResult<TomlDependency<P>>,
) -> CargoResult<TomlDependency<P>> {
cx: &mut Context<'_, '_>,
get_inheritable: impl FnOnce() -> CargoResult<InheritableFields>,
) -> CargoResult<TomlDependency> {
match self {
TomlDependency::Detailed(d) => Ok(TomlDependency::Detailed(d)),
TomlDependency::Simple(s) => Ok(TomlDependency::Simple(s)),
Expand All @@ -2256,28 +2284,30 @@ impl<P: ResolveToPath + Clone> TomlDependency<P> {
optional,
}) => {
cargo_features.require(Feature::workspace_inheritance())?;
get_ws_dependency().context(format!(
let inheritable = get_inheritable()?;
inheritable.get_dependency(label).context(format!(
"error reading `dependencies.{}` from workspace root manifest's `workspace.dependencies.{}`",
label, label
)).map(|dep| {
match dep {
TomlDependency::Simple(s) => {
if optional.is_some() || features.is_some() {
TomlDependency::Detailed(DetailedTomlDependency::<P> {
Ok(TomlDependency::Detailed(DetailedTomlDependency {
version: Some(s),
optional,
features,
..Default::default()
})
}))
} else {
TomlDependency::Simple(s)
Ok(TomlDependency::Simple(s))
}
},
TomlDependency::Detailed(d) => {
let mut dep = d.clone();
dep.add_features(features);
dep.update_optional(optional);
TomlDependency::Detailed(dep)
dep.resolve_path(label,inheritable.ws_root(), cx.root)?;
Ok(TomlDependency::Detailed(dep))
},
TomlDependency::Workspace(_) => {
unreachable!(
Expand All @@ -2288,7 +2318,7 @@ impl<P: ResolveToPath + Clone> TomlDependency<P> {
)
},
}
})
})?
}
TomlDependency::Workspace(TomlWorkspaceDependency {
workspace: false, ..
Expand Down Expand Up @@ -2543,7 +2573,9 @@ impl<P: ResolveToPath + Clone> DetailedTomlDependency<P> {
}
Ok(dep)
}
}

impl DetailedTomlDependency {
Comment on lines +2576 to +2578
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the new block?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was due to DetailedTomlDependency::<P>, same as TomlDependency::<P>. Resolving a relative path requires us to replace the path with a String currently. When you would try to do that on a non-string P it would throw errors. You also should never call any methods here or in TomlDependency on anything other than a String for P. I believe this is the case due to everything being a String except .cargo/config.toml

fn add_features(&mut self, features: Option<Vec<String>>) {
self.features = match (self.features.clone(), features.clone()) {
(Some(dep_feat), Some(inherit_feat)) => Some(
Expand All @@ -2561,6 +2593,23 @@ impl<P: ResolveToPath + Clone> DetailedTomlDependency<P> {
fn update_optional(&mut self, optional: Option<bool>) {
self.optional = optional;
}

fn resolve_path(
&mut self,
name: &str,
root_path: &Path,
package_root: &Path,
) -> CargoResult<()> {
if let Some(rel_path) = &self.path {
self.path = Some(resolve_relative_path(
name,
root_path,
package_root,
rel_path,
)?)
}
Ok(())
}
}

#[derive(Default, Serialize, Deserialize, Debug, Clone)]
Expand Down
Loading