Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cargo run supports --package argument #3691

Merged
merged 1 commit into from
Feb 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 24 additions & 17 deletions src/bin/run.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::iter::FromIterator;

use cargo::core::Workspace;
use cargo::ops::{self, MessageFormat, Packages};
use cargo::util::{CliResult, CliError, Config, Human};
Expand All @@ -7,6 +9,7 @@ use cargo::util::important_paths::{find_root_manifest_for_wd};
pub struct Options {
flag_bin: Option<String>,
flag_example: Option<String>,
flag_package: Option<String>,
flag_jobs: Option<u32>,
flag_features: Vec<String>,
flag_all_features: bool,
Expand All @@ -30,22 +33,23 @@ Usage:
cargo run [options] [--] [<args>...]

Options:
-h, --help Print this message
--bin NAME Name of the bin target to run
--example NAME Name of the example target to run
-j N, --jobs N Number of parallel jobs, defaults to # of CPUs
--release Build artifacts in release mode, with optimizations
--features FEATURES Space-separated list of features to also build
--all-features Build all available features
--no-default-features Do not build the `default` feature
--target TRIPLE Build for the target triple
--manifest-path PATH Path to the manifest to execute
-v, --verbose ... Use verbose output (-vv very verbose/build.rs output)
-q, --quiet No output printed to stdout
--color WHEN Coloring: auto, always, never
--message-format FMT Error format: human, json [default: human]
--frozen Require Cargo.lock and cache are up to date
--locked Require Cargo.lock is up to date
-h, --help Print this message
--bin NAME Name of the bin target to run
--example NAME Name of the example target to run
-p SPEC, --package SPEC Package with the target to run
-j N, --jobs N Number of parallel jobs, defaults to # of CPUs
--release Build artifacts in release mode, with optimizations
--features FEATURES Space-separated list of features to also build
--all-features Build all available features
--no-default-features Do not build the `default` feature
--target TRIPLE Build for the target triple
--manifest-path PATH Path to the manifest to execute
-v, --verbose ... Use verbose output (-vv very verbose/build.rs output)
-q, --quiet No output printed to stdout
--color WHEN Coloring: auto, always, never
--message-format FMT Error format: human, json [default: human]
--frozen Require Cargo.lock and cache are up to date
--locked Require Cargo.lock is up to date

If neither `--bin` nor `--example` are given, then if the project only has one
bin target it will be run. Otherwise `--bin` specifies the bin target to run,
Expand Down Expand Up @@ -74,14 +78,17 @@ pub fn execute(options: Options, config: &Config) -> CliResult {
examples.push(s);
}

let packages = Vec::from_iter(options.flag_package.iter().cloned());
let spec = Packages::Packages(&packages);

let compile_opts = ops::CompileOptions {
config: config,
jobs: options.flag_jobs,
target: options.flag_target.as_ref().map(|t| &t[..]),
features: &options.flag_features,
all_features: options.flag_all_features,
no_default_features: options.flag_no_default_features,
spec: Packages::Packages(&[]),
spec: spec,
release: options.flag_release,
mode: ops::CompileMode::Build,
filter: if examples.is_empty() && bins.is_empty() {
Expand Down
4 changes: 2 additions & 2 deletions src/cargo/ops/cargo_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pub enum MessageFormat {
Json
}

#[derive(Clone, Copy, PartialEq, Eq)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Packages<'a> {
All,
Packages(&'a [String]),
Expand Down Expand Up @@ -141,7 +141,7 @@ pub fn compile<'a>(ws: &Workspace<'a>, options: &CompileOptions<'a>)
}

pub fn compile_with_exec<'a>(ws: &Workspace<'a>,
options: &CompileOptions<'a>,
options: &CompileOptions<'a>,
exec: Arc<Executor>)
-> CargoResult<ops::Compilation<'a>> {
for member in ws.members() {
Expand Down
23 changes: 18 additions & 5 deletions src/cargo/ops/cargo_run.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
use std::path::Path;

use ops::{self, CompileFilter};
use util::{self, CargoResult, ProcessError};
use ops::{self, CompileFilter, Packages};
use util::{self, human, CargoResult, ProcessError};
use core::Workspace;

pub fn run(ws: &Workspace,
options: &ops::CompileOptions,
args: &[String]) -> CargoResult<Option<ProcessError>> {
let config = ws.config();
let root = ws.current()?;

let mut bins = root.manifest().targets().iter().filter(|a| {
let pkg = match options.spec {
Packages::All => unreachable!("cargo run supports single package only"),
Packages::Packages(xs) => match xs.len() {
0 => ws.current()?,
1 => ws.members()
.find(|pkg| pkg.name() == xs[0])
.ok_or_else(|| human(
format!("package `{}` is not a member of the workspace", xs[0])
))?,
_ => unreachable!("cargo run supports single package only"),
}
};

let mut bins = pkg.manifest().targets().iter().filter(|a| {
!a.is_lib() && !a.is_custom_build() && match options.filter {
CompileFilter::Everything => a.is_bin(),
CompileFilter::Only { .. } => options.filter.matches(a),
Expand Down Expand Up @@ -41,14 +53,15 @@ pub fn run(ws: &Workspace,
}

let compile = ops::compile(ws, options)?;
assert_eq!(compile.binaries.len(), 1);
let exe = &compile.binaries[0];
let exe = match util::without_prefix(&exe, config.cwd()) {
Some(path) if path.file_name() == Some(path.as_os_str())
=> Path::new(".").join(path).to_path_buf(),
Some(path) => path.to_path_buf(),
None => exe.to_path_buf(),
};
let mut process = compile.target_process(exe, &root)?;
let mut process = compile.target_process(exe, &pkg)?;
process.args(args).cwd(config.cwd());

config.shell().status("Running", process.to_string())?;
Expand Down
77 changes: 77 additions & 0 deletions tests/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -652,3 +652,80 @@ fn fail_no_extra_verbose() {
.with_stdout("")
.with_stderr(""));
}

#[test]
fn run_multiple_packages() {
let p = project("foo")
.file("foo/Cargo.toml", r#"
[package]
name = "foo"
version = "0.0.1"
authors = []

[workspace]

[dependencies]
d1 = { path = "d1" }
d2 = { path = "d2" }
d3 = { path = "../d3" } # outside of the workspace

[[bin]]
name = "foo"
"#)
.file("foo/src/foo.rs", "fn main() { println!(\"foo\"); }")
.file("foo/d1/Cargo.toml", r#"
[package]
name = "d1"
version = "0.0.1"
authors = []

[[bin]]
name = "d1"
"#)
.file("foo/d1/src/lib.rs", "")
.file("foo/d1/src/main.rs", "fn main() { println!(\"d1\"); }")
.file("foo/d2/Cargo.toml", r#"
[package]
name = "d2"
version = "0.0.1"
authors = []

[[bin]]
name = "d2"
"#)
.file("foo/d2/src/main.rs", "fn main() { println!(\"d2\"); }")
.file("d3/Cargo.toml", r#"
[package]
name = "d3"
version = "0.0.1"
authors = []
"#)
.file("d3/src/main.rs", "fn main() { println!(\"d2\"); }");

let p = p.build();

let cargo = || {
let mut process_builder = p.cargo("run");
process_builder.cwd(p.root().join("foo"));
process_builder
};

assert_that(cargo().arg("-p").arg("d1"),
execs().with_status(0).with_stdout("d1"));

assert_that(cargo().arg("-p").arg("d2").arg("--bin").arg("d2"),
execs().with_status(0).with_stdout("d2"));

assert_that(cargo(),
execs().with_status(0).with_stdout("foo"));

assert_that(cargo().arg("-p").arg("d1").arg("-p").arg("d2"),
execs()
.with_status(1)
.with_stderr_contains("[ERROR] Invalid arguments."));

assert_that(cargo().arg("-p").arg("d3"),
execs()
.with_status(101)
.with_stderr_contains("[ERROR] package `d3` is not a member of the workspace"));
}