Skip to content

Commit

Permalink
Build transitive dev-dependencies when needed
Browse files Browse the repository at this point in the history
When running `cargo test -p foo` where `foo` is a crate in the current
workspace, build and link `foo`'s dev-dependencies. Fixes #860.
  • Loading branch information
mbrubeck committed Sep 27, 2016
1 parent 4f57637 commit bb058d9
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 13 deletions.
16 changes: 10 additions & 6 deletions src/cargo/ops/cargo_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use std::sync::Arc;

use core::registry::PackageRegistry;
use core::{Source, SourceId, PackageSet, Package, Target};
use core::{Profile, TargetKind, Profiles, Workspace};
use core::{Profile, TargetKind, Profiles, Workspace, PackageIdSpec};
use core::resolver::{Method, Resolve};
use ops::{self, BuildOutput, ExecEngine};
use sources::PathSource;
Expand Down Expand Up @@ -97,7 +97,8 @@ pub fn resolve_dependencies<'a>(ws: &Workspace<'a>,
source: Option<Box<Source + 'a>>,
features: Vec<String>,
all_features: bool,
no_default_features: bool)
no_default_features: bool,
spec: &'a [String])
-> CargoResult<(PackageSet<'a>, Resolve)> {

let mut registry = try!(PackageRegistry::new(ws.config()));
Expand Down Expand Up @@ -128,9 +129,13 @@ pub fn resolve_dependencies<'a>(ws: &Workspace<'a>,
}
};

let specs = try!(spec.iter().map(|p| PackageIdSpec::parse(p))
.collect::<CargoResult<Vec<_>>>());

let resolved_with_overrides =
try!(ops::resolve_with_previous(&mut registry, ws,
method, Some(&resolve), None));
method, Some(&resolve), None,
&specs));

let packages = ops::get_resolved_packages(&resolved_with_overrides,
registry);
Expand Down Expand Up @@ -164,9 +169,8 @@ pub fn compile_ws<'a>(ws: &Workspace<'a>,
try!(generate_targets(root_package, profiles, mode, filter, release));
}

let (packages, resolve_with_overrides) = {
try!(resolve_dependencies(ws, source, features, all_features, no_default_features))
};
let (packages, resolve_with_overrides) =
try!(resolve_dependencies(ws, source, features, all_features, no_default_features, spec));

let mut pkgids = Vec::new();
if spec.len() > 0 {
Expand Down
5 changes: 3 additions & 2 deletions src/cargo/ops/cargo_generate_lockfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub fn generate_lockfile(ws: &Workspace) -> CargoResult<()> {
let mut registry = try!(PackageRegistry::new(ws.config()));
let resolve = try!(ops::resolve_with_previous(&mut registry, ws,
Method::Everything,
None, None));
None, None, &[]));
try!(ops::write_pkg_lockfile(ws, &resolve));
Ok(())
}
Expand Down Expand Up @@ -78,7 +78,8 @@ pub fn update_lockfile(ws: &Workspace, opts: &UpdateOptions)
ws,
Method::Everything,
Some(&previous_resolve),
Some(&to_avoid)));
Some(&to_avoid),
&[]));

// Summarize what is changing for the user.
let print_change = |status: &str, msg: String| {
Expand Down
3 changes: 2 additions & 1 deletion src/cargo/ops/cargo_output_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ fn metadata_full(ws: &Workspace,
None,
opt.features.clone(),
opt.all_features,
opt.no_default_features));
opt.no_default_features,
&[]));
let (packages, resolve) = deps;

let packages = try!(packages.package_ids()
Expand Down
10 changes: 6 additions & 4 deletions src/cargo/ops/resolve.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::{HashMap, HashSet};

use core::{PackageId, SourceId, Workspace};
use core::{PackageId, PackageIdSpec, SourceId, Workspace};
use core::registry::PackageRegistry;
use core::resolver::{self, Resolve, Method};
use ops;
Expand All @@ -16,7 +16,7 @@ pub fn resolve_ws(registry: &mut PackageRegistry, ws: &Workspace)
let prev = try!(ops::load_pkg_lockfile(ws));
let resolve = try!(resolve_with_previous(registry, ws,
Method::Everything,
prev.as_ref(), None));
prev.as_ref(), None, &[]));

// Avoid writing a lockfile if we are `cargo install`ing a non local package.
if ws.current_opt().map(|pkg| pkg.package_id().source_id().is_path()).unwrap_or(true) {
Expand All @@ -38,7 +38,8 @@ pub fn resolve_with_previous<'a>(registry: &mut PackageRegistry,
ws: &Workspace,
method: Method,
previous: Option<&'a Resolve>,
to_avoid: Option<&HashSet<&'a PackageId>>)
to_avoid: Option<&HashSet<&'a PackageId>>,
specs: &[PackageIdSpec])
-> CargoResult<Resolve> {
// Here we place an artificial limitation that all non-registry sources
// cannot be locked at more than one revision. This means that if a git
Expand Down Expand Up @@ -67,7 +68,8 @@ pub fn resolve_with_previous<'a>(registry: &mut PackageRegistry,
if let Method::Required { .. } = method {
assert!(previous.is_some());
if let Some(current) = ws.current_opt() {
if member.package_id() != current.package_id() {
if member.package_id() != current.package_id() &&
!specs.iter().any(|spec| spec.matches(member.package_id())) {
continue;
}
}
Expand Down
48 changes: 48 additions & 0 deletions tests/workspaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -962,3 +962,51 @@ fn you_cannot_generate_lockfile_for_empty_workspaces() {
error: you can't generate a lockfile for an empty workspace.
"));
}

#[test]
fn workspace_with_transitive_dev_deps() {
let p = project("foo")
.file("Cargo.toml", r#"
[project]
name = "foo"
version = "0.5.0"
authors = ["mbrubeck@example.com"]
[dependencies.bar]
path = "bar"
[workspace]
"#)
.file("src/main.rs", r#"fn main() {}"#)
.file("bar/Cargo.toml", r#"
[project]
name = "bar"
version = "0.5.0"
authors = ["mbrubeck@example.com"]
[dev-dependencies.baz]
path = "../baz"
"#)
.file("bar/src/lib.rs", r#"
pub fn init() {}
#[cfg(test)]
#[test]
fn test() {
extern crate baz;
baz::do_stuff();
}
"#)
.file("baz/Cargo.toml", r#"
[project]
name = "baz"
version = "0.5.0"
authors = ["mbrubeck@example.com"]
"#)
.file("baz/src/lib.rs", r#"pub fn do_stuff() {}"#);
p.build();

assert_that(p.cargo("test").args(&["-p", "bar"]),
execs().with_status(0));
}

0 comments on commit bb058d9

Please sign in to comment.