Skip to content

Commit 403fbe2

Browse files
committed
Auto merge of #13518 - baby230211:fix/strip-feature-dev-dep, r=epage
fix: strip feature dep when dep is dev dep ### What does this PR try to resolve? This change aims to strip features dependencies without a version key to be published. If a dev-dependency is missing the version, it will be stripped from the packaged manifest. The features table may contains the deps in following places. - Target - normal - dev - build - normal-and-dev - normal - dev - build - normal-and-dev ### How should we test and review this PR? See the initial commit, it shows current behavior that will cause error when feature has deps that point to dev_dep and doesn't have a version specified. Title | orignal toml | published toml | ---- | ---- | ---- | Before | feature = ["dev-dep/feature"] <br/> [dev-dependencies] <br/> dev-dep = { .., features: ["feature"] } | feature = ["dev-dep/feature"] <br/> [dev-dependencies] <br/> dev-dep = { .., features: ["feature"] } | After | feature = ["dev-dep/feature"] <br/> [dev-dependencies] <br/> dev-dep = { .., features: ["feature"] } | feature = [] <br/> [dev-dependencies] ``` Fix: #12225
2 parents 601670a + 75130eb commit 403fbe2

File tree

3 files changed

+369
-5
lines changed

3 files changed

+369
-5
lines changed

src/cargo/ops/registry/publish.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
//! [1]: https://doc.rust-lang.org/nightly/cargo/reference/registry-web-api.html#publish
44
55
use std::collections::BTreeMap;
6+
use std::collections::BTreeSet;
67
use std::collections::HashSet;
78
use std::fs::File;
89
use std::time::Duration;
@@ -20,6 +21,7 @@ use crate::core::dependency::DepKind;
2021
use crate::core::manifest::ManifestMetadata;
2122
use crate::core::resolver::CliFeatures;
2223
use crate::core::Dependency;
24+
use crate::core::FeatureValue;
2325
use crate::core::Package;
2426
use crate::core::PackageIdSpecQuery;
2527
use crate::core::SourceId;
@@ -33,6 +35,7 @@ use crate::sources::CRATES_IO_REGISTRY;
3335
use crate::util::auth;
3436
use crate::util::cache_lock::CacheLockMode;
3537
use crate::util::context::JobsConfig;
38+
use crate::util::interning::InternedString;
3639
use crate::util::Progress;
3740
use crate::util::ProgressStyle;
3841
use crate::CargoResult;
@@ -412,13 +415,31 @@ fn transmit(
412415
return Ok(());
413416
}
414417

418+
let deps_set = deps
419+
.iter()
420+
.map(|dep| dep.name.clone())
421+
.collect::<BTreeSet<String>>();
422+
415423
let string_features = match manifest.original().features() {
416424
Some(features) => features
417425
.iter()
418426
.map(|(feat, values)| {
419427
(
420428
feat.to_string(),
421-
values.iter().map(|fv| fv.to_string()).collect(),
429+
values
430+
.iter()
431+
.filter(|fv| {
432+
let feature_value = FeatureValue::new(InternedString::new(fv));
433+
match feature_value {
434+
FeatureValue::Dep { dep_name }
435+
| FeatureValue::DepFeature { dep_name, .. } => {
436+
deps_set.contains(&dep_name.to_string())
437+
}
438+
_ => true,
439+
}
440+
})
441+
.map(|fv| fv.to_string())
442+
.collect(),
422443
)
423444
})
424445
.collect::<BTreeMap<String, Vec<String>>>(),

src/cargo/util/toml/mod.rs

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ use crate::AlreadyPrintedError;
99
use anyhow::{anyhow, bail, Context as _};
1010
use cargo_platform::Platform;
1111
use cargo_util::paths;
12-
use cargo_util_schemas::manifest;
1312
use cargo_util_schemas::manifest::RustVersion;
13+
use cargo_util_schemas::manifest::{self, TomlManifest};
1414
use itertools::Itertools;
1515
use lazycell::LazyCell;
1616
use pathdiff::diff_paths;
@@ -21,7 +21,7 @@ use crate::core::compiler::{CompileKind, CompileTarget};
2121
use crate::core::dependency::{Artifact, ArtifactTarget, DepKind};
2222
use crate::core::manifest::{ManifestMetadata, TargetSourcePath, Warnings};
2323
use crate::core::resolver::ResolveBehavior;
24-
use crate::core::{find_workspace_root, resolve_relative_path, CliUnstable};
24+
use crate::core::{find_workspace_root, resolve_relative_path, CliUnstable, FeatureValue};
2525
use crate::core::{Dependency, Manifest, PackageId, Summary, Target};
2626
use crate::core::{Edition, EitherManifest, Feature, Features, VirtualManifest, Workspace};
2727
use crate::core::{GitReference, PackageIdSpec, SourceId, WorkspaceConfig, WorkspaceRootConfig};
@@ -316,7 +316,7 @@ pub fn prepare_for_publish(
316316
}
317317
}
318318
let all = |_d: &manifest::TomlDependency| true;
319-
return Ok(manifest::TomlManifest {
319+
let mut manifest = manifest::TomlManifest {
320320
package: Some(package),
321321
project: None,
322322
profile: me.profile.clone(),
@@ -366,7 +366,52 @@ pub fn prepare_for_publish(
366366
badges: me.badges.clone(),
367367
cargo_features: me.cargo_features.clone(),
368368
lints: me.lints.clone(),
369-
});
369+
};
370+
strip_features(&mut manifest);
371+
return Ok(manifest);
372+
373+
fn strip_features(manifest: &mut TomlManifest) {
374+
fn insert_dep_name(
375+
dep_name_set: &mut BTreeSet<manifest::PackageName>,
376+
deps: Option<&BTreeMap<manifest::PackageName, manifest::InheritableDependency>>,
377+
) {
378+
let Some(deps) = deps else {
379+
return;
380+
};
381+
deps.iter().for_each(|(k, _v)| {
382+
dep_name_set.insert(k.clone());
383+
});
384+
}
385+
let mut dep_name_set = BTreeSet::new();
386+
insert_dep_name(&mut dep_name_set, manifest.dependencies.as_ref());
387+
insert_dep_name(&mut dep_name_set, manifest.dev_dependencies());
388+
insert_dep_name(&mut dep_name_set, manifest.build_dependencies());
389+
if let Some(target_map) = manifest.target.as_ref() {
390+
target_map.iter().for_each(|(_k, v)| {
391+
insert_dep_name(&mut dep_name_set, v.dependencies.as_ref());
392+
insert_dep_name(&mut dep_name_set, v.dev_dependencies());
393+
insert_dep_name(&mut dep_name_set, v.build_dependencies());
394+
});
395+
}
396+
let features = manifest.features.as_mut();
397+
398+
let Some(features) = features else {
399+
return;
400+
};
401+
402+
features.values_mut().for_each(|feature_deps| {
403+
feature_deps.retain(|feature_dep| {
404+
let feature_value = FeatureValue::new(InternedString::new(feature_dep));
405+
match feature_value {
406+
FeatureValue::Dep { dep_name } | FeatureValue::DepFeature { dep_name, .. } => {
407+
let k = &manifest::PackageName::new(dep_name.to_string()).unwrap();
408+
dep_name_set.contains(k)
409+
}
410+
_ => true,
411+
}
412+
});
413+
});
414+
}
370415

371416
fn map_deps(
372417
gctx: &GlobalContext,

0 commit comments

Comments
 (0)