&options.flag_z)?;
let root = find_root_manifest_for_wd(options.flag_manifest_path, config.cwd())?;
- let ws = Workspace::new(&root, config)?;
+ let mut ws = Workspace::new(&root, config)?;
+ if config.cli_unstable().avoid_dev_deps {
+ ws.set_require_optional_deps(false);
+ }
let spec = Packages::from_flags(options.flag_all,
&options.flag_exclude,
pub struct CliUnstable {
pub print_im_a_teapot: bool,
pub unstable_options: bool,
+ pub avoid_dev_deps: bool,
}
impl CliUnstable {
match k {
"print-im-a-teapot" => self.print_im_a_teapot = parse_bool(v)?,
"unstable-options" => self.unstable_options = true,
+ "avoid-dev-deps" => self.avoid_dev_deps = true,
_ => bail!("unknown `-Z` flag specified: {}", k),
}
#[derive(Clone, Copy)]
pub enum Method<'a> {
- Everything,
+ Everything, // equivalent to Required { dev_deps: true, all_features: true, .. }
Required {
dev_deps: bool,
features: &'a [String],
+ all_features: bool,
uses_default_features: bool,
},
}
+impl<'r> Method<'r> {
+ pub fn split_features(features: &[String]) -> Vec<String> {
+ features.iter()
+ .flat_map(|s| s.split_whitespace())
+ .flat_map(|s| s.split(','))
+ .filter(|s| !s.is_empty())
+ .map(|s| s.to_string())
+ .collect::<Vec<String>>()
+ }
+}
+
// Information about the dependencies for a crate, a tuple of:
//
// (dependency info, candidates, features activated)
let method = Method::Required {
dev_deps: false,
features: &features,
+ all_features: false,
uses_default_features: dep.uses_default_features(),
};
trace!("{}[{}]>{} trying {}", parent.name(), cur, dep.name(),
-> CargoResult<Requirements<'a>> {
let mut reqs = Requirements::new(s);
match *method {
- Method::Everything => {
+ Method::Everything |
+ Method::Required { all_features: true, .. } => {
for key in s.features().keys() {
reqs.require_feature(key)?;
}
}
debug!("checking if {} is already activated", summary.package_id());
let (features, use_default) = match *method {
+ Method::Everything |
+ Method::Required { all_features: true, .. } => return false,
Method::Required { features, uses_default_features, .. } => {
(features, uses_default_features)
}
- Method::Everything => return false,
};
let has_default_feature = summary.features().contains_key("default");
// True if this workspace should enforce optional dependencies even when
// not needed; false if this workspace should only enforce dependencies
- // needed by the current configuration (such as in cargo install).
+ // needed by the current configuration (such as in cargo install). In some
+ // cases `false` also results in the non-enforcement of dev-dependencies.
require_optional_deps: bool,
}
self.require_optional_deps
}
+ pub fn set_require_optional_deps<'a>(&'a mut self, require_optional_deps: bool) -> &mut Workspace<'cfg> {
+ self.require_optional_deps = require_optional_deps;
+ self
+ }
+
/// Finds the root of a workspace for the crate whose manifest is located
/// at `manifest_path`.
///
use core::{Source, Package, Target};
use core::{Profile, TargetKind, Profiles, Workspace, PackageId, PackageIdSpec};
-use core::resolver::Resolve;
+use core::resolver::{Resolve, Method};
use ops::{self, BuildOutput, Executor, DefaultExecutor};
use util::config::Config;
use util::{CargoResult, profile};
let profiles = ws.profiles();
let specs = spec.into_package_id_specs(ws)?;
- let resolve = ops::resolve_ws_precisely(ws,
- source,
- features,
- all_features,
- no_default_features,
- &specs)?;
+ let features = Method::split_features(features);
+ let method = Method::Required {
+ dev_deps: ws.require_optional_deps() || filter.need_dev_deps(mode),
+ features: &features,
+ all_features,
+ uses_default_features: !no_default_features,
+ };
+ let resolve = ops::resolve_ws_with_method(ws,
+ source,
+ method,
+ &specs,
+ )?;
let (packages, resolve_with_overrides) = resolve;
if specs.is_empty() {
}
}
+ pub fn need_dev_deps(&self, mode: CompileMode) -> bool {
+ match mode {
+ CompileMode::Test | CompileMode::Doctest | CompileMode::Bench => true,
+ CompileMode::Build | CompileMode::Doc { .. } | CompileMode::Check { .. } => match *self
+ {
+ CompileFilter::Default { .. } => false,
+ CompileFilter::Only {
+ ref examples,
+ ref tests,
+ ref benches,
+ ..
+ } => examples.is_specific() || tests.is_specific() || benches.is_specific(),
+ },
+ }
+ }
+
pub fn matches(&self, target: &Target) -> bool {
match *self {
CompileFilter::Default { .. } => true,
let ws = match overidden_target_dir {
Some(dir) => Workspace::ephemeral(pkg, config, Some(dir), false)?,
- None => Workspace::new(pkg.manifest_path(), config)?,
+ None => {
+ let mut ws = Workspace::new(pkg.manifest_path(), config)?;
+ ws.set_require_optional_deps(false);
+ ws
+ }
};
let pkg = ws.current()?;
pub use self::registry::configure_http_handle;
pub use self::cargo_fetch::fetch;
pub use self::cargo_pkgid::pkgid;
-pub use self::resolve::{resolve_ws, resolve_ws_precisely, resolve_with_previous};
+pub use self::resolve::{resolve_ws, resolve_ws_precisely, resolve_ws_with_method, resolve_with_previous};
pub use self::cargo_output_metadata::{output_metadata, OutputMetadataOptions, ExportInfo};
mod cargo_clean;
no_default_features: bool,
specs: &[PackageIdSpec])
-> CargoResult<(PackageSet<'a>, Resolve)> {
- let features = features.iter()
- .flat_map(|s| s.split_whitespace())
- .flat_map(|s| s.split(','))
- .filter(|s| !s.is_empty())
- .map(|s| s.to_string())
- .collect::<Vec<String>>();
+ let features = Method::split_features(features);
+ let method = if all_features {
+ Method::Everything
+ } else {
+ Method::Required {
+ dev_deps: true,
+ features: &features,
+ all_features: false,
+ uses_default_features: !no_default_features,
+ }
+ };
+ resolve_ws_with_method(ws, source, method, specs)
+}
+pub fn resolve_ws_with_method<'a>(ws: &Workspace<'a>,
+ source: Option<Box<Source + 'a>>,
+ method: Method,
+ specs: &[PackageIdSpec])
+ -> CargoResult<(PackageSet<'a>, Resolve)> {
let mut registry = PackageRegistry::new(ws.config())?;
if let Some(source) = source {
registry.add_preloaded(source);
None
};
- let method = if all_features {
- Method::Everything
- } else {
- Method::Required {
- dev_deps: true, // TODO: remove this option?
- features: &features,
- uses_default_features: !no_default_features,
- }
- };
-
let resolved_with_overrides =
ops::resolve_with_previous(&mut registry, ws,
method, resolve.as_ref(), None,
let base = Method::Required {
dev_deps: dev_deps,
features: &[],
+ all_features: false,
uses_default_features: true,
};
let member_id = member.package_id();