mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-28 11:20:36 +00:00
Auto merge of #13603 - epage:toml3, r=weihanglo
refactor(toml): Expose surce/spans for VirtualManifests ### What does this PR try to resolve? This is a follow up to #13593, expanding support from `Manifest` to `VirtualManifest` as well. This also does other clean up along the way in preparation for making a more explicit `resolve_toml` phase. ### How should we test and review this PR? ### Additional information
This commit is contained in:
commit
d438c80c45
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -470,7 +470,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cargo-util-schemas"
|
||||
version = "0.3.0"
|
||||
version = "0.3.1"
|
||||
dependencies = [
|
||||
"semver",
|
||||
"serde",
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "cargo-util-schemas"
|
||||
version = "0.3.0"
|
||||
version = "0.3.1"
|
||||
rust-version = "1.76.0" # MSRV:1
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
@ -26,7 +26,7 @@ pub use rust_version::RustVersion;
|
||||
pub use rust_version::RustVersionError;
|
||||
|
||||
/// This type is used to deserialize `Cargo.toml` files.
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Default, Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct TomlManifest {
|
||||
// when adding new fields, be sure to check whether `requires_package` should disallow them
|
||||
|
@ -12,6 +12,7 @@ use crate::util::errors::CargoResult;
|
||||
use crate::GlobalContext;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::BuildConfig;
|
||||
|
||||
@ -103,10 +104,13 @@ pub fn resolve_std<'gctx>(
|
||||
/*custom_metadata*/ &None,
|
||||
));
|
||||
let virtual_manifest = crate::core::VirtualManifest::new(
|
||||
Rc::default(),
|
||||
Rc::new(toml_edit::ImDocument::parse("".to_owned()).expect("empty is valid TOML")),
|
||||
Rc::default(),
|
||||
Rc::default(),
|
||||
/*replace*/ Vec::new(),
|
||||
patch,
|
||||
ws_config,
|
||||
/*profiles*/ None,
|
||||
crate::core::Features::default(),
|
||||
None,
|
||||
);
|
||||
|
@ -546,7 +546,6 @@ impl Features {
|
||||
warnings: &mut Vec<String>,
|
||||
) -> CargoResult<()> {
|
||||
let nightly_features_allowed = self.nightly_features_allowed;
|
||||
let is_local = self.is_local;
|
||||
let Some((slot, feature)) = self.status(feature_name) else {
|
||||
bail!("unknown cargo feature `{}`", feature_name)
|
||||
};
|
||||
@ -567,19 +566,15 @@ impl Features {
|
||||
|
||||
match feature.stability {
|
||||
Status::Stable => {
|
||||
// The user can't do anything about non-local packages.
|
||||
// Warnings are usually suppressed, but just being cautious here.
|
||||
if is_local {
|
||||
let warning = format!(
|
||||
"the cargo feature `{}` has been stabilized in the {} \
|
||||
let warning = format!(
|
||||
"the cargo feature `{}` has been stabilized in the {} \
|
||||
release and is no longer necessary to be listed in the \
|
||||
manifest\n {}",
|
||||
feature_name,
|
||||
feature.version,
|
||||
see_docs()
|
||||
);
|
||||
warnings.push(warning);
|
||||
}
|
||||
feature_name,
|
||||
feature.version,
|
||||
see_docs()
|
||||
);
|
||||
warnings.push(warning);
|
||||
}
|
||||
Status::Unstable if !nightly_features_allowed => bail!(
|
||||
"the cargo feature `{}` requires a nightly version of \
|
||||
|
@ -44,6 +44,7 @@ pub struct Manifest {
|
||||
// alternate forms of manifests:
|
||||
contents: Rc<String>,
|
||||
document: Rc<toml_edit::ImDocument<String>>,
|
||||
original_toml: Rc<TomlManifest>,
|
||||
resolved_toml: Rc<TomlManifest>,
|
||||
summary: Summary,
|
||||
|
||||
@ -57,7 +58,6 @@ pub struct Manifest {
|
||||
include: Vec<String>,
|
||||
metadata: ManifestMetadata,
|
||||
custom_metadata: Option<toml::Value>,
|
||||
profiles: Option<TomlProfiles>,
|
||||
publish: Option<Vec<String>>,
|
||||
replace: Vec<(PackageIdSpec, Dependency)>,
|
||||
patch: HashMap<Url, Vec<Dependency>>,
|
||||
@ -87,10 +87,16 @@ pub struct Warnings(Vec<DelayedWarning>);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VirtualManifest {
|
||||
// alternate forms of manifests:
|
||||
contents: Rc<String>,
|
||||
document: Rc<toml_edit::ImDocument<String>>,
|
||||
original_toml: Rc<TomlManifest>,
|
||||
resolved_toml: Rc<TomlManifest>,
|
||||
|
||||
// this form of manifest:
|
||||
replace: Vec<(PackageIdSpec, Dependency)>,
|
||||
patch: HashMap<Url, Vec<Dependency>>,
|
||||
workspace: WorkspaceConfig,
|
||||
profiles: Option<TomlProfiles>,
|
||||
warnings: Warnings,
|
||||
features: Features,
|
||||
resolve_behavior: Option<ResolveBehavior>,
|
||||
@ -396,6 +402,7 @@ impl Manifest {
|
||||
pub fn new(
|
||||
contents: Rc<String>,
|
||||
document: Rc<toml_edit::ImDocument<String>>,
|
||||
original_toml: Rc<TomlManifest>,
|
||||
resolved_toml: Rc<TomlManifest>,
|
||||
summary: Summary,
|
||||
|
||||
@ -407,7 +414,6 @@ impl Manifest {
|
||||
links: Option<String>,
|
||||
metadata: ManifestMetadata,
|
||||
custom_metadata: Option<toml::Value>,
|
||||
profiles: Option<TomlProfiles>,
|
||||
publish: Option<Vec<String>>,
|
||||
replace: Vec<(PackageIdSpec, Dependency)>,
|
||||
patch: HashMap<Url, Vec<Dependency>>,
|
||||
@ -425,6 +431,7 @@ impl Manifest {
|
||||
Manifest {
|
||||
contents,
|
||||
document,
|
||||
original_toml,
|
||||
resolved_toml,
|
||||
summary,
|
||||
|
||||
@ -437,7 +444,6 @@ impl Manifest {
|
||||
links,
|
||||
metadata,
|
||||
custom_metadata,
|
||||
profiles,
|
||||
publish,
|
||||
replace,
|
||||
patch,
|
||||
@ -462,6 +468,10 @@ impl Manifest {
|
||||
pub fn document(&self) -> &toml_edit::ImDocument<String> {
|
||||
&self.document
|
||||
}
|
||||
/// The [`TomlManifest`] as parsed from [`Manifest::document`]
|
||||
pub fn original_toml(&self) -> &TomlManifest {
|
||||
&self.original_toml
|
||||
}
|
||||
/// The [`TomlManifest`] with all fields expanded
|
||||
pub fn resolved_toml(&self) -> &TomlManifest {
|
||||
&self.resolved_toml
|
||||
@ -514,7 +524,7 @@ impl Manifest {
|
||||
&self.warnings
|
||||
}
|
||||
pub fn profiles(&self) -> Option<&TomlProfiles> {
|
||||
self.profiles.as_ref()
|
||||
self.resolved_toml.profile.as_ref()
|
||||
}
|
||||
pub fn publish(&self) -> &Option<Vec<String>> {
|
||||
&self.publish
|
||||
@ -622,24 +632,47 @@ impl Manifest {
|
||||
|
||||
impl VirtualManifest {
|
||||
pub fn new(
|
||||
contents: Rc<String>,
|
||||
document: Rc<toml_edit::ImDocument<String>>,
|
||||
original_toml: Rc<TomlManifest>,
|
||||
resolved_toml: Rc<TomlManifest>,
|
||||
replace: Vec<(PackageIdSpec, Dependency)>,
|
||||
patch: HashMap<Url, Vec<Dependency>>,
|
||||
workspace: WorkspaceConfig,
|
||||
profiles: Option<TomlProfiles>,
|
||||
features: Features,
|
||||
resolve_behavior: Option<ResolveBehavior>,
|
||||
) -> VirtualManifest {
|
||||
VirtualManifest {
|
||||
contents,
|
||||
document,
|
||||
original_toml,
|
||||
resolved_toml,
|
||||
replace,
|
||||
patch,
|
||||
workspace,
|
||||
profiles,
|
||||
warnings: Warnings::new(),
|
||||
features,
|
||||
resolve_behavior,
|
||||
}
|
||||
}
|
||||
|
||||
/// The raw contents of the original TOML
|
||||
pub fn contents(&self) -> &str {
|
||||
self.contents.as_str()
|
||||
}
|
||||
/// Collection of spans for the original TOML
|
||||
pub fn document(&self) -> &toml_edit::ImDocument<String> {
|
||||
&self.document
|
||||
}
|
||||
/// The [`TomlManifest`] as parsed from [`VirtualManifest::document`]
|
||||
pub fn original_toml(&self) -> &TomlManifest {
|
||||
&self.original_toml
|
||||
}
|
||||
/// The [`TomlManifest`] with all fields expanded
|
||||
pub fn resolved_toml(&self) -> &TomlManifest {
|
||||
&self.resolved_toml
|
||||
}
|
||||
|
||||
pub fn replace(&self) -> &[(PackageIdSpec, Dependency)] {
|
||||
&self.replace
|
||||
}
|
||||
@ -653,7 +686,7 @@ impl VirtualManifest {
|
||||
}
|
||||
|
||||
pub fn profiles(&self) -> Option<&TomlProfiles> {
|
||||
self.profiles.as_ref()
|
||||
self.resolved_toml.profile.as_ref()
|
||||
}
|
||||
|
||||
pub fn warnings_mut(&mut self) -> &mut Warnings {
|
||||
|
@ -52,15 +52,16 @@ pub fn read_manifest(
|
||||
read_toml_string(path, gctx).map_err(|err| ManifestError::new(err, path.into()))?;
|
||||
let document =
|
||||
parse_document(&contents).map_err(|e| emit_diagnostic(e.into(), &contents, path, gctx))?;
|
||||
let toml = deserialize_toml(&document)
|
||||
let original_toml = deserialize_toml(&document)
|
||||
.map_err(|e| emit_diagnostic(e.into(), &contents, path, gctx))?;
|
||||
|
||||
(|| {
|
||||
if toml.package().is_some() {
|
||||
to_real_manifest(contents, document, toml, source_id, path, gctx)
|
||||
if original_toml.package().is_some() {
|
||||
to_real_manifest(contents, document, original_toml, source_id, path, gctx)
|
||||
.map(EitherManifest::Real)
|
||||
} else {
|
||||
to_virtual_manifest(toml, source_id, path, gctx).map(EitherManifest::Virtual)
|
||||
to_virtual_manifest(contents, document, original_toml, source_id, path, gctx)
|
||||
.map(EitherManifest::Virtual)
|
||||
}
|
||||
})()
|
||||
.map_err(|err| {
|
||||
@ -456,38 +457,11 @@ pub fn prepare_for_publish(
|
||||
pub fn to_real_manifest(
|
||||
contents: String,
|
||||
document: toml_edit::ImDocument<String>,
|
||||
me: manifest::TomlManifest,
|
||||
original_toml: manifest::TomlManifest,
|
||||
source_id: SourceId,
|
||||
manifest_file: &Path,
|
||||
gctx: &GlobalContext,
|
||||
) -> CargoResult<Manifest> {
|
||||
fn get_ws(
|
||||
gctx: &GlobalContext,
|
||||
resolved_path: &Path,
|
||||
workspace_config: &WorkspaceConfig,
|
||||
) -> CargoResult<InheritableFields> {
|
||||
match workspace_config {
|
||||
WorkspaceConfig::Root(root) => Ok(root.inheritable().clone()),
|
||||
WorkspaceConfig::Member {
|
||||
root: Some(ref path_to_root),
|
||||
} => {
|
||||
let path = resolved_path
|
||||
.parent()
|
||||
.unwrap()
|
||||
.join(path_to_root)
|
||||
.join("Cargo.toml");
|
||||
let root_path = paths::normalize_path(&path);
|
||||
inheritable_from_path(gctx, root_path)
|
||||
}
|
||||
WorkspaceConfig::Member { root: None } => {
|
||||
match find_workspace_root(&resolved_path, gctx)? {
|
||||
Some(path_to_root) => inheritable_from_path(gctx, path_to_root),
|
||||
None => Err(anyhow!("failed to find a workspace root")),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let embedded = is_embedded(manifest_file);
|
||||
let package_root = manifest_file.parent().unwrap();
|
||||
if !package_root.is_dir() {
|
||||
@ -497,7 +471,7 @@ pub fn to_real_manifest(
|
||||
);
|
||||
};
|
||||
|
||||
if let Some(deps) = me
|
||||
if let Some(deps) = original_toml
|
||||
.workspace
|
||||
.as_ref()
|
||||
.and_then(|ws| ws.dependencies.as_ref())
|
||||
@ -515,49 +489,36 @@ pub fn to_real_manifest(
|
||||
let mut warnings = vec![];
|
||||
let mut errors = vec![];
|
||||
|
||||
warn_on_unused(&me._unused_keys, &mut warnings);
|
||||
|
||||
// Parse features first so they will be available when parsing other parts of the TOML.
|
||||
let empty = Vec::new();
|
||||
let cargo_features = me.cargo_features.as_ref().unwrap_or(&empty);
|
||||
let cargo_features = original_toml.cargo_features.as_ref().unwrap_or(&empty);
|
||||
let features = Features::new(cargo_features, gctx, &mut warnings, source_id.is_path())?;
|
||||
|
||||
let mut package = match (&me.package, &me.project) {
|
||||
let mut package = match (&original_toml.package, &original_toml.project) {
|
||||
(Some(_), Some(project)) => {
|
||||
if source_id.is_path() {
|
||||
gctx.shell().warn(format!(
|
||||
"manifest at `{}` contains both `project` and `package`, \
|
||||
warnings.push(format!(
|
||||
"manifest at `{}` contains both `project` and `package`, \
|
||||
this could become a hard error in the future",
|
||||
package_root.display()
|
||||
))?;
|
||||
}
|
||||
package_root.display()
|
||||
));
|
||||
project.clone()
|
||||
}
|
||||
(Some(package), None) => package.clone(),
|
||||
(None, Some(project)) => {
|
||||
if source_id.is_path() {
|
||||
gctx.shell().warn(format!(
|
||||
"manifest at `{}` contains `[project]` instead of `[package]`, \
|
||||
warnings.push(format!(
|
||||
"manifest at `{}` contains `[project]` instead of `[package]`, \
|
||||
this could become a hard error in the future",
|
||||
package_root.display()
|
||||
))?;
|
||||
}
|
||||
package_root.display()
|
||||
));
|
||||
project.clone()
|
||||
}
|
||||
(None, None) => bail!("no `package` section found"),
|
||||
};
|
||||
|
||||
let workspace_config = match (me.workspace.as_ref(), package.workspace.as_ref()) {
|
||||
let workspace_config = match (original_toml.workspace.as_ref(), package.workspace.as_ref()) {
|
||||
(Some(toml_config), None) => {
|
||||
let lints = toml_config.lints.clone();
|
||||
let lints = verify_lints(lints)?;
|
||||
let inheritable = InheritableFields {
|
||||
package: toml_config.package.clone(),
|
||||
dependencies: toml_config.dependencies.clone(),
|
||||
lints,
|
||||
_ws_root: package_root.to_path_buf(),
|
||||
};
|
||||
if let Some(ws_deps) = &inheritable.dependencies {
|
||||
verify_lints(toml_config.lints.as_ref())?;
|
||||
if let Some(ws_deps) = &toml_config.dependencies {
|
||||
for (name, dep) in ws_deps {
|
||||
unused_dep_keys(
|
||||
name,
|
||||
@ -567,14 +528,7 @@ pub fn to_real_manifest(
|
||||
);
|
||||
}
|
||||
}
|
||||
let ws_root_config = WorkspaceRootConfig::new(
|
||||
package_root,
|
||||
&toml_config.members,
|
||||
&toml_config.default_members,
|
||||
&toml_config.exclude,
|
||||
&Some(inheritable),
|
||||
&toml_config.metadata,
|
||||
);
|
||||
let ws_root_config = to_workspace_config(toml_config, package_root);
|
||||
gctx.ws_roots
|
||||
.borrow_mut()
|
||||
.insert(package_root.to_path_buf(), ws_root_config.clone());
|
||||
@ -589,16 +543,16 @@ pub fn to_real_manifest(
|
||||
),
|
||||
};
|
||||
|
||||
let package_name = package.name.trim();
|
||||
let package_name = &package.name;
|
||||
if package_name.contains(':') {
|
||||
features.require(Feature::open_namespaces())?;
|
||||
}
|
||||
|
||||
let resolved_path = package_root.join("Cargo.toml");
|
||||
|
||||
let inherit_cell: LazyCell<InheritableFields> = LazyCell::new();
|
||||
let inherit =
|
||||
|| inherit_cell.try_borrow_with(|| get_ws(gctx, &resolved_path, &workspace_config));
|
||||
let inherit = || {
|
||||
inherit_cell
|
||||
.try_borrow_with(|| load_inheritable_fields(gctx, manifest_file, &workspace_config))
|
||||
};
|
||||
|
||||
let version = package
|
||||
.version
|
||||
@ -704,7 +658,10 @@ pub fn to_real_manifest(
|
||||
|
||||
let resolve_behavior = match (
|
||||
package.resolver.as_ref(),
|
||||
me.workspace.as_ref().and_then(|ws| ws.resolver.as_ref()),
|
||||
original_toml
|
||||
.workspace
|
||||
.as_ref()
|
||||
.and_then(|ws| ws.resolver.as_ref()),
|
||||
) {
|
||||
(None, None) => None,
|
||||
(Some(s), None) | (None, Some(s)) => Some(ResolveBehavior::from_manifest(s)?),
|
||||
@ -718,7 +675,7 @@ pub fn to_real_manifest(
|
||||
// If we have a lib with no path, use the inferred lib or else the package name.
|
||||
let targets = targets(
|
||||
&features,
|
||||
&me,
|
||||
&original_toml,
|
||||
package_name,
|
||||
package_root,
|
||||
edition,
|
||||
@ -789,7 +746,7 @@ pub fn to_real_manifest(
|
||||
|
||||
let inheritable = || {
|
||||
inherit_cell.try_borrow_with(|| {
|
||||
get_ws(
|
||||
load_inheritable_fields(
|
||||
manifest_ctx.gctx,
|
||||
&manifest_ctx.root.join("Cargo.toml"),
|
||||
&workspace_config,
|
||||
@ -851,12 +808,12 @@ pub fn to_real_manifest(
|
||||
// Collect the dependencies.
|
||||
let dependencies = process_dependencies(
|
||||
&mut manifest_ctx,
|
||||
me.dependencies.as_ref(),
|
||||
original_toml.dependencies.as_ref(),
|
||||
None,
|
||||
&workspace_config,
|
||||
&inherit_cell,
|
||||
)?;
|
||||
if me.dev_dependencies.is_some() && me.dev_dependencies2.is_some() {
|
||||
if original_toml.dev_dependencies.is_some() && original_toml.dev_dependencies2.is_some() {
|
||||
warn_on_deprecated(
|
||||
"dev-dependencies",
|
||||
package_name,
|
||||
@ -864,7 +821,7 @@ pub fn to_real_manifest(
|
||||
manifest_ctx.warnings,
|
||||
);
|
||||
}
|
||||
let dev_deps = me.dev_dependencies();
|
||||
let dev_deps = original_toml.dev_dependencies();
|
||||
let dev_deps = process_dependencies(
|
||||
&mut manifest_ctx,
|
||||
dev_deps,
|
||||
@ -872,7 +829,7 @@ pub fn to_real_manifest(
|
||||
&workspace_config,
|
||||
&inherit_cell,
|
||||
)?;
|
||||
if me.build_dependencies.is_some() && me.build_dependencies2.is_some() {
|
||||
if original_toml.build_dependencies.is_some() && original_toml.build_dependencies2.is_some() {
|
||||
warn_on_deprecated(
|
||||
"build-dependencies",
|
||||
package_name,
|
||||
@ -880,7 +837,7 @@ pub fn to_real_manifest(
|
||||
manifest_ctx.warnings,
|
||||
);
|
||||
}
|
||||
let build_deps = me.build_dependencies();
|
||||
let build_deps = original_toml.build_dependencies();
|
||||
let build_deps = process_dependencies(
|
||||
&mut manifest_ctx,
|
||||
build_deps,
|
||||
@ -889,17 +846,17 @@ pub fn to_real_manifest(
|
||||
&inherit_cell,
|
||||
)?;
|
||||
|
||||
let lints = me
|
||||
let lints = original_toml
|
||||
.lints
|
||||
.clone()
|
||||
.map(|mw| lints_inherit_with(mw, || inherit()?.lints()))
|
||||
.transpose()?;
|
||||
let lints = verify_lints(lints)?;
|
||||
verify_lints(lints.as_ref())?;
|
||||
let default = manifest::TomlLints::default();
|
||||
let rustflags = lints_to_rustflags(lints.as_ref().unwrap_or(&default));
|
||||
|
||||
let mut target: BTreeMap<String, manifest::TomlPlatform> = BTreeMap::new();
|
||||
for (name, platform) in me.target.iter().flatten() {
|
||||
for (name, platform) in original_toml.target.iter().flatten() {
|
||||
manifest_ctx.platform = {
|
||||
let platform: Platform = name.parse()?;
|
||||
platform.check_cfg_attributes(manifest_ctx.warnings);
|
||||
@ -961,8 +918,8 @@ pub fn to_real_manifest(
|
||||
} else {
|
||||
Some(target)
|
||||
};
|
||||
let replace = replace(&me, &mut manifest_ctx)?;
|
||||
let patch = patch(&me, &mut manifest_ctx)?;
|
||||
let replace = replace(&original_toml, &mut manifest_ctx)?;
|
||||
let patch = patch(&original_toml, &mut manifest_ctx)?;
|
||||
|
||||
{
|
||||
let mut names_sources = BTreeMap::new();
|
||||
@ -997,7 +954,8 @@ pub fn to_real_manifest(
|
||||
let summary = Summary::new(
|
||||
pkgid,
|
||||
deps,
|
||||
&me.features
|
||||
&original_toml
|
||||
.features
|
||||
.as_ref()
|
||||
.unwrap_or(&empty_features)
|
||||
.iter()
|
||||
@ -1070,7 +1028,7 @@ pub fn to_real_manifest(
|
||||
.map(|mw| field_inherit_with(mw, "categories", || inherit()?.categories()))
|
||||
.transpose()?
|
||||
.unwrap_or_default(),
|
||||
badges: me
|
||||
badges: original_toml
|
||||
.badges
|
||||
.clone()
|
||||
.map(|mw| field_inherit_with(mw, "badges", || inherit()?.badges()))
|
||||
@ -1134,8 +1092,7 @@ pub fn to_real_manifest(
|
||||
.as_ref()
|
||||
.map(|_| manifest::InheritableField::Value(include.clone()));
|
||||
|
||||
let profiles = me.profile.clone();
|
||||
if let Some(profiles) = &profiles {
|
||||
if let Some(profiles) = &original_toml.profile {
|
||||
let cli_unstable = gctx.cli_unstable();
|
||||
validate_profiles(profiles, cli_unstable, &features, &mut warnings)?;
|
||||
}
|
||||
@ -1194,26 +1151,26 @@ pub fn to_real_manifest(
|
||||
.map(CompileKind::Target);
|
||||
let custom_metadata = package.metadata.clone();
|
||||
let resolved_toml = manifest::TomlManifest {
|
||||
cargo_features: me.cargo_features.clone(),
|
||||
cargo_features: original_toml.cargo_features.clone(),
|
||||
package: Some(package.clone()),
|
||||
project: None,
|
||||
profile: me.profile.clone(),
|
||||
lib: me.lib.clone(),
|
||||
bin: me.bin.clone(),
|
||||
example: me.example.clone(),
|
||||
test: me.test.clone(),
|
||||
bench: me.bench.clone(),
|
||||
profile: original_toml.profile.clone(),
|
||||
lib: original_toml.lib.clone(),
|
||||
bin: original_toml.bin.clone(),
|
||||
example: original_toml.example.clone(),
|
||||
test: original_toml.test.clone(),
|
||||
bench: original_toml.bench.clone(),
|
||||
dependencies,
|
||||
dev_dependencies: dev_deps,
|
||||
dev_dependencies2: None,
|
||||
build_dependencies: build_deps,
|
||||
build_dependencies2: None,
|
||||
features: me.features.clone(),
|
||||
features: original_toml.features.clone(),
|
||||
target,
|
||||
replace: me.replace.clone(),
|
||||
patch: me.patch.clone(),
|
||||
workspace: me.workspace.clone(),
|
||||
badges: me
|
||||
replace: original_toml.replace.clone(),
|
||||
patch: original_toml.patch.clone(),
|
||||
workspace: original_toml.workspace.clone(),
|
||||
badges: original_toml
|
||||
.badges
|
||||
.as_ref()
|
||||
.map(|_| manifest::InheritableField::Value(metadata.badges.clone())),
|
||||
@ -1226,6 +1183,7 @@ pub fn to_real_manifest(
|
||||
let mut manifest = Manifest::new(
|
||||
Rc::new(contents),
|
||||
Rc::new(document),
|
||||
Rc::new(original_toml),
|
||||
Rc::new(resolved_toml),
|
||||
summary,
|
||||
default_kind,
|
||||
@ -1236,7 +1194,6 @@ pub fn to_real_manifest(
|
||||
package.links.clone(),
|
||||
metadata,
|
||||
custom_metadata,
|
||||
profiles,
|
||||
publish,
|
||||
replace,
|
||||
patch,
|
||||
@ -1252,16 +1209,17 @@ pub fn to_real_manifest(
|
||||
embedded,
|
||||
);
|
||||
if package.license_file.is_some() && package.license.is_some() {
|
||||
manifest.warnings_mut().add_warning(
|
||||
warnings.push(
|
||||
"only one of `license` or `license-file` is necessary\n\
|
||||
`license` should be used if the package license can be expressed \
|
||||
with a standard SPDX expression.\n\
|
||||
`license-file` should be used if the package uses a non-standard license.\n\
|
||||
See https://doc.rust-lang.org/cargo/reference/manifest.html#the-license-and-license-file-fields \
|
||||
for more information."
|
||||
.to_string(),
|
||||
.to_owned(),
|
||||
);
|
||||
}
|
||||
warn_on_unused(&manifest.original_toml()._unused_keys, &mut warnings);
|
||||
for warning in warnings {
|
||||
manifest.warnings_mut().add_warning(warning);
|
||||
}
|
||||
@ -1274,15 +1232,67 @@ pub fn to_real_manifest(
|
||||
Ok(manifest)
|
||||
}
|
||||
|
||||
fn to_workspace_config(
|
||||
resolved_toml: &manifest::TomlWorkspace,
|
||||
package_root: &Path,
|
||||
) -> WorkspaceRootConfig {
|
||||
let inheritable = InheritableFields {
|
||||
package: resolved_toml.package.clone(),
|
||||
dependencies: resolved_toml.dependencies.clone(),
|
||||
lints: resolved_toml.lints.clone(),
|
||||
_ws_root: package_root.to_owned(),
|
||||
};
|
||||
let ws_root_config = WorkspaceRootConfig::new(
|
||||
package_root,
|
||||
&resolved_toml.members,
|
||||
&resolved_toml.default_members,
|
||||
&resolved_toml.exclude,
|
||||
&Some(inheritable),
|
||||
&resolved_toml.metadata,
|
||||
);
|
||||
ws_root_config
|
||||
}
|
||||
|
||||
fn load_inheritable_fields(
|
||||
gctx: &GlobalContext,
|
||||
resolved_path: &Path,
|
||||
workspace_config: &WorkspaceConfig,
|
||||
) -> CargoResult<InheritableFields> {
|
||||
match workspace_config {
|
||||
WorkspaceConfig::Root(root) => Ok(root.inheritable().clone()),
|
||||
WorkspaceConfig::Member {
|
||||
root: Some(ref path_to_root),
|
||||
} => {
|
||||
let path = resolved_path
|
||||
.parent()
|
||||
.unwrap()
|
||||
.join(path_to_root)
|
||||
.join("Cargo.toml");
|
||||
let root_path = paths::normalize_path(&path);
|
||||
inheritable_from_path(gctx, root_path)
|
||||
}
|
||||
WorkspaceConfig::Member { root: None } => {
|
||||
match find_workspace_root(&resolved_path, gctx)? {
|
||||
Some(path_to_root) => inheritable_from_path(gctx, path_to_root),
|
||||
None => Err(anyhow!("failed to find a workspace root")),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn to_virtual_manifest(
|
||||
me: manifest::TomlManifest,
|
||||
contents: String,
|
||||
document: toml_edit::ImDocument<String>,
|
||||
original_toml: manifest::TomlManifest,
|
||||
source_id: SourceId,
|
||||
manifest_file: &Path,
|
||||
gctx: &GlobalContext,
|
||||
) -> CargoResult<VirtualManifest> {
|
||||
let root = manifest_file.parent().unwrap();
|
||||
|
||||
if let Some(deps) = me
|
||||
let mut resolved_toml = original_toml.clone();
|
||||
|
||||
if let Some(deps) = original_toml
|
||||
.workspace
|
||||
.as_ref()
|
||||
.and_then(|ws| ws.dependencies.as_ref())
|
||||
@ -1297,17 +1307,17 @@ fn to_virtual_manifest(
|
||||
}
|
||||
}
|
||||
|
||||
for field in me.requires_package() {
|
||||
for field in original_toml.requires_package() {
|
||||
bail!("this virtual manifest specifies a `{field}` section, which is not allowed");
|
||||
}
|
||||
|
||||
let mut warnings = Vec::new();
|
||||
let mut deps = Vec::new();
|
||||
let empty = Vec::new();
|
||||
let cargo_features = me.cargo_features.as_ref().unwrap_or(&empty);
|
||||
let cargo_features = original_toml.cargo_features.as_ref().unwrap_or(&empty);
|
||||
let features = Features::new(cargo_features, gctx, &mut warnings, source_id.is_path())?;
|
||||
|
||||
warn_on_unused(&me._unused_keys, &mut warnings);
|
||||
resolved_toml._unused_keys = Default::default();
|
||||
|
||||
let (replace, patch) = {
|
||||
let mut manifest_ctx = ManifestContext {
|
||||
@ -1320,38 +1330,23 @@ fn to_virtual_manifest(
|
||||
root,
|
||||
};
|
||||
(
|
||||
replace(&me, &mut manifest_ctx)?,
|
||||
patch(&me, &mut manifest_ctx)?,
|
||||
replace(&original_toml, &mut manifest_ctx)?,
|
||||
patch(&original_toml, &mut manifest_ctx)?,
|
||||
)
|
||||
};
|
||||
let profiles = me.profile.clone();
|
||||
if let Some(profiles) = &profiles {
|
||||
if let Some(profiles) = &original_toml.profile {
|
||||
validate_profiles(profiles, gctx.cli_unstable(), &features, &mut warnings)?;
|
||||
}
|
||||
let resolve_behavior = me
|
||||
let resolve_behavior = original_toml
|
||||
.workspace
|
||||
.as_ref()
|
||||
.and_then(|ws| ws.resolver.as_deref())
|
||||
.map(|r| ResolveBehavior::from_manifest(r))
|
||||
.transpose()?;
|
||||
let workspace_config = match me.workspace {
|
||||
let workspace_config = match original_toml.workspace {
|
||||
Some(ref toml_config) => {
|
||||
let lints = toml_config.lints.clone();
|
||||
let lints = verify_lints(lints)?;
|
||||
let inheritable = InheritableFields {
|
||||
package: toml_config.package.clone(),
|
||||
dependencies: toml_config.dependencies.clone(),
|
||||
lints,
|
||||
_ws_root: root.to_path_buf(),
|
||||
};
|
||||
let ws_root_config = WorkspaceRootConfig::new(
|
||||
root,
|
||||
&toml_config.members,
|
||||
&toml_config.default_members,
|
||||
&toml_config.exclude,
|
||||
&Some(inheritable),
|
||||
&toml_config.metadata,
|
||||
);
|
||||
verify_lints(toml_config.lints.as_ref())?;
|
||||
let ws_root_config = to_workspace_config(toml_config, root);
|
||||
gctx.ws_roots
|
||||
.borrow_mut()
|
||||
.insert(root.to_path_buf(), ws_root_config.clone());
|
||||
@ -1362,13 +1357,18 @@ fn to_virtual_manifest(
|
||||
}
|
||||
};
|
||||
let mut manifest = VirtualManifest::new(
|
||||
Rc::new(contents),
|
||||
Rc::new(document),
|
||||
Rc::new(original_toml),
|
||||
Rc::new(resolved_toml),
|
||||
replace,
|
||||
patch,
|
||||
workspace_config,
|
||||
profiles,
|
||||
features,
|
||||
resolve_behavior,
|
||||
);
|
||||
|
||||
warn_on_unused(&manifest.original_toml()._unused_keys, &mut warnings);
|
||||
for warning in warnings {
|
||||
manifest.warnings_mut().add_warning(warning);
|
||||
}
|
||||
@ -1471,12 +1471,12 @@ struct ManifestContext<'a, 'b> {
|
||||
features: &'a Features,
|
||||
}
|
||||
|
||||
fn verify_lints(lints: Option<manifest::TomlLints>) -> CargoResult<Option<manifest::TomlLints>> {
|
||||
fn verify_lints(lints: Option<&manifest::TomlLints>) -> CargoResult<()> {
|
||||
let Some(lints) = lints else {
|
||||
return Ok(None);
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
for (tool, lints) in &lints {
|
||||
for (tool, lints) in lints {
|
||||
let supported = ["rust", "clippy", "rustdoc"];
|
||||
if !supported.contains(&tool.as_str()) {
|
||||
let supported = supported.join(", ");
|
||||
@ -1499,7 +1499,7 @@ fn verify_lints(lints: Option<manifest::TomlLints>) -> CargoResult<Option<manife
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Some(lints))
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn lints_to_rustflags(lints: &manifest::TomlLints) -> Vec<String> {
|
||||
|
Loading…
x
Reference in New Issue
Block a user