Avoid installing dev-dependencies
authorXimin Luo <infinity0@pwned.gg>
Sun, 15 Apr 2018 06:58:29 +0000 (12:28 +0530)
committerVasudev Kamath <vasudev@copyninja.info>
Sun, 15 Apr 2018 06:58:29 +0000 (12:28 +0530)
Applied-Upstream: https://github.com/rust-lang/cargo/pull/5012
Applied-Upstream: https://github.com/rust-lang/cargo/pull/5186

Gbp-Pq: Name 1001_PR5012.patch

src/bin/build.rs
src/cargo/core/features.rs
src/cargo/core/resolver/mod.rs
src/cargo/core/workspace.rs
src/cargo/ops/cargo_compile.rs
src/cargo/ops/cargo_install.rs
src/cargo/ops/mod.rs
src/cargo/ops/resolve.rs

index 889052068e477e5cb4bfcfd295d37cd9eb04efed..b388c36f5cea3499d15bfe7a2bbb4df752f63240 100644 (file)
@@ -98,7 +98,10 @@ pub fn execute(options: Options, config: &mut Config) -> CliResult {
                      &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,
index 4cb5ac5e44b09d92fc0dcd27d821638fad20d1b3..727a1cb94eb9e723715c1bbebcb473c882855acf 100644 (file)
@@ -232,6 +232,7 @@ impl Features {
 pub struct CliUnstable {
     pub print_im_a_teapot: bool,
     pub unstable_options: bool,
+    pub avoid_dev_deps: bool,
 }
 
 impl CliUnstable {
@@ -262,6 +263,7 @@ 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),
         }
 
index cfefbf48992c08a7dcaf64e2cee3f2de2b4326b2..871cc3a2e5c00cae682b0485b80a9e621cbec352 100644 (file)
@@ -96,14 +96,26 @@ pub struct DepsNotReplaced<'a> {
 
 #[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)
@@ -731,6 +743,7 @@ fn activate_deps_loop<'a>(mut cx: Context<'a>,
         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(),
@@ -996,7 +1009,8 @@ fn build_requirements<'a, 'b: 'a>(s: &'a Summary, method: &'b Method)
                                   -> 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)?;
             }
@@ -1042,10 +1056,11 @@ impl<'a> Context<'a> {
         }
         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");
index 5d21dd8d41a6919499b8f916af8c302e258e73be..c2e1a3e4d624eda8e8f14a191506f19f26fe1dd7 100644 (file)
@@ -64,7 +64,8 @@ pub struct Workspace<'cfg> {
 
     // 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,
 }
 
@@ -300,6 +301,11 @@ impl<'cfg> Workspace<'cfg> {
         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`.
     ///
index cc3400268f96fbc9dc94cea93c7899c515e971ee..7dad97df20a4970377bcfc3d4ec7993f36f0347a 100644 (file)
@@ -29,7 +29,7 @@ use std::sync::Arc;
 
 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};
@@ -226,12 +226,18 @@ pub fn compile_ws<'a>(ws: &Workspace<'a>,
     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() {
@@ -413,6 +419,22 @@ impl<'a> CompileFilter<'a> {
         }
     }
 
+    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,
index c85923e453b2d46ca2e6a91bec3c4324aa7330b7..703a96da44f53fff56094549aac7e86ddf9700f1 100644 (file)
@@ -175,7 +175,11 @@ fn install_one(root: &Filesystem,
 
     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()?;
 
index 7c4a33d4ba278a41ad9c25168a08e8ffe216d1f7..5da0781ec87a06a560121b4ee31dce4441cf5c7e 100644 (file)
@@ -22,7 +22,7 @@ pub use self::registry::{modify_owners, yank, OwnersOptions, PublishOpts};
 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;
index 2ccf3b394fa64c67ad37caa4bac9d8394de6d295..11f12e250800f750a7843d406a5677b20756fe31 100644 (file)
@@ -29,13 +29,25 @@ pub fn resolve_ws_precisely<'a>(ws: &Workspace<'a>,
                                 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);
@@ -66,16 +78,6 @@ pub fn resolve_ws_precisely<'a>(ws: &Workspace<'a>,
         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,
@@ -219,6 +221,7 @@ pub fn resolve_with_previous<'a>(registry: &mut PackageRegistry,
                 let base = Method::Required {
                     dev_deps: dev_deps,
                     features: &[],
+                    all_features: false,
                     uses_default_features: true,
                 };
                 let member_id = member.package_id();