mirror of
https://github.com/rust-lang/cargo.git
synced 2025-10-01 11:30:39 +00:00
Fix optional dependencies and required dev-deps
This fixes an accidental bug introduced in #5300 by ensuring a local map keeps track of the fact that there can be multiple dependencies for one name Closes #5453
This commit is contained in:
parent
acea5e2f3c
commit
02b0dba36b
@ -340,15 +340,18 @@ fn activate_deps_loop(
|
|||||||
backtracked = true;
|
backtracked = true;
|
||||||
Ok((candidate, has_another))
|
Ok((candidate, has_another))
|
||||||
}
|
}
|
||||||
None => Err(activation_error(
|
None => {
|
||||||
&cx,
|
debug!("no candidates found");
|
||||||
registry.registry,
|
Err(activation_error(
|
||||||
&parent,
|
&cx,
|
||||||
&dep,
|
registry.registry,
|
||||||
&conflicting_activations,
|
&parent,
|
||||||
&candidates,
|
&dep,
|
||||||
config,
|
&conflicting_activations,
|
||||||
)),
|
&candidates,
|
||||||
|
config,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
@ -140,10 +140,12 @@ fn build_feature_map(
|
|||||||
namespaced: bool,
|
namespaced: bool,
|
||||||
) -> CargoResult<FeatureMap> {
|
) -> CargoResult<FeatureMap> {
|
||||||
use self::FeatureValue::*;
|
use self::FeatureValue::*;
|
||||||
let dep_map: HashMap<_, _> = dependencies
|
let mut dep_map = HashMap::new();
|
||||||
.iter()
|
for dep in dependencies.iter() {
|
||||||
.map(|d| (d.name().as_str(), d))
|
dep_map.entry(dep.name().as_str())
|
||||||
.collect();
|
.or_insert(Vec::new())
|
||||||
|
.push(dep);
|
||||||
|
}
|
||||||
|
|
||||||
let mut map = BTreeMap::new();
|
let mut map = BTreeMap::new();
|
||||||
for (feature, list) in features.iter() {
|
for (feature, list) in features.iter() {
|
||||||
@ -159,7 +161,7 @@ fn build_feature_map(
|
|||||||
let mut dependency_found = if namespaced {
|
let mut dependency_found = if namespaced {
|
||||||
match dep_map.get(feature.as_str()) {
|
match dep_map.get(feature.as_str()) {
|
||||||
Some(ref dep_data) => {
|
Some(ref dep_data) => {
|
||||||
if !dep_data.is_optional() {
|
if !dep_data.iter().any(|d| d.is_optional()) {
|
||||||
bail!(
|
bail!(
|
||||||
"Feature `{}` includes the dependency of the same name, but this is \
|
"Feature `{}` includes the dependency of the same name, but this is \
|
||||||
left implicit in the features included by this feature.\n\
|
left implicit in the features included by this feature.\n\
|
||||||
@ -196,7 +198,9 @@ fn build_feature_map(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let is_optional_dep = dep_data.map_or(false, |d| d.is_optional());
|
let is_optional_dep = dep_data.iter()
|
||||||
|
.flat_map(|d| d.iter())
|
||||||
|
.any(|d| d.is_optional());
|
||||||
if let FeatureValue::Crate(ref dep_name) = val {
|
if let FeatureValue::Crate(ref dep_name) = val {
|
||||||
// If we have a dependency value, check if this is the dependency named
|
// If we have a dependency value, check if this is the dependency named
|
||||||
// the same as the feature that we were looking for.
|
// the same as the feature that we were looking for.
|
||||||
|
@ -113,13 +113,19 @@ impl<'cfg> RegistryIndex<'cfg> {
|
|||||||
// interpretation of each line here and older cargo will simply
|
// interpretation of each line here and older cargo will simply
|
||||||
// ignore the new lines.
|
// ignore the new lines.
|
||||||
ret.extend(lines.filter_map(|line| {
|
ret.extend(lines.filter_map(|line| {
|
||||||
self.parse_registry_package(line).ok().and_then(|v| {
|
let (summary, locked) = match self.parse_registry_package(line) {
|
||||||
if online || load.is_crate_downloaded(v.0.package_id()) {
|
Ok(p) => p,
|
||||||
Some(v)
|
Err(e) => {
|
||||||
} else {
|
info!("failed to parse `{}` registry package: {}", name, e);
|
||||||
None
|
trace!("line: {}", line);
|
||||||
|
return None
|
||||||
}
|
}
|
||||||
})
|
};
|
||||||
|
if online || load.is_crate_downloaded(summary.package_id()) {
|
||||||
|
Some((summary, locked))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1999,3 +1999,35 @@ fn namespaced_same_name() {
|
|||||||
execs().with_status(0),
|
execs().with_status(0),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn only_dep_is_optional() {
|
||||||
|
Package::new("bar", "0.1.0").publish();
|
||||||
|
|
||||||
|
let p = project("foo")
|
||||||
|
.file(
|
||||||
|
"Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[project]
|
||||||
|
name = "foo"
|
||||||
|
version = "0.0.1"
|
||||||
|
authors = []
|
||||||
|
|
||||||
|
[features]
|
||||||
|
foo = ['bar']
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bar = { version = "0.1", optional = true }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
bar = "0.1"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.file("src/main.rs", "fn main() {}")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_that(
|
||||||
|
p.cargo("build"),
|
||||||
|
execs().with_status(0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user