Stabilize default-run

This commit is contained in:
Eric Huss 2019-06-21 11:36:53 -07:00
parent 142603ae22
commit 7d7fe6797a
20 changed files with 131 additions and 225 deletions

View File

@ -10,7 +10,7 @@ use std::fs;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use cargo::core::shell::Shell; use cargo::core::shell::Shell;
use cargo::util::{self, command_prelude, lev_distance, CargoResult, CliResult, Config}; use cargo::util::{self, closest_msg, command_prelude, CargoResult, CliResult, Config};
use cargo::util::{CliError, ProcessError}; use cargo::util::{CliError, ProcessError};
mod cli; mod cli;
@ -113,18 +113,6 @@ fn list_commands(config: &Config) -> BTreeSet<CommandInfo> {
commands commands
} }
fn find_closest(config: &Config, cmd: &str) -> Option<String> {
let cmds = list_commands(config);
// Only consider candidates with a lev_distance of 3 or less so we don't
// suggest out-of-the-blue options.
cmds.into_iter()
.map(|c| c.name())
.map(|c| (lev_distance(&c, cmd), c))
.filter(|&(d, _)| d < 4)
.min_by_key(|a| a.0)
.map(|slot| slot.1)
}
fn execute_external_subcommand(config: &Config, cmd: &str, args: &[&str]) -> CliResult { fn execute_external_subcommand(config: &Config, cmd: &str, args: &[&str]) -> CliResult {
let command_exe = format!("cargo-{}{}", cmd, env::consts::EXE_SUFFIX); let command_exe = format!("cargo-{}{}", cmd, env::consts::EXE_SUFFIX);
let path = search_directories(config) let path = search_directories(config)
@ -134,14 +122,9 @@ fn execute_external_subcommand(config: &Config, cmd: &str, args: &[&str]) -> Cli
let command = match path { let command = match path {
Some(command) => command, Some(command) => command,
None => { None => {
let err = match find_closest(config, cmd) { let cmds = list_commands(config);
Some(closest) => failure::format_err!( let did_you_mean = closest_msg(cmd, cmds.iter(), |c| c.name());
"no such subcommand: `{}`\n\n\tDid you mean `{}`?\n", let err = failure::format_err!("no such subcommand: `{}`{}", cmd, did_you_mean);
cmd,
closest
),
None => failure::format_err!("no such subcommand: `{}`", cmd),
};
return Err(CliError::new(err, 101)); return Err(CliError::new(err, 101));
} }
}; };

View File

@ -196,7 +196,7 @@ features! {
[unstable] namespaced_features: bool, [unstable] namespaced_features: bool,
// "default-run" manifest option, // "default-run" manifest option,
[unstable] default_run: bool, [stable] default_run: bool,
// Declarative build scripts. // Declarative build scripts.
[unstable] metabuild: bool, [unstable] metabuild: bool,

View File

@ -518,12 +518,6 @@ impl Manifest {
})?; })?;
} }
if self.default_run.is_some() {
self.features
.require(Feature::default_run())
.chain_err(|| failure::format_err!("the `default-run` manifest key is unstable"))?;
}
Ok(()) Ok(())
} }

View File

@ -25,7 +25,7 @@ use crate::ops;
use crate::util::config::PackageCacheLock; use crate::util::config::PackageCacheLock;
use crate::util::errors::{CargoResult, CargoResultExt, HttpNot200}; use crate::util::errors::{CargoResult, CargoResultExt, HttpNot200};
use crate::util::network::Retry; use crate::util::network::Retry;
use crate::util::{self, internal, lev_distance, Config, Progress, ProgressStyle}; use crate::util::{self, internal, Config, Progress, ProgressStyle};
/// Information about a package that is available somewhere in the file system. /// Information about a package that is available somewhere in the file system.
/// ///
@ -193,21 +193,6 @@ impl Package {
self.targets().iter().any(|t| t.is_custom_build()) self.targets().iter().any(|t| t.is_custom_build())
} }
pub fn find_closest_target(
&self,
target: &str,
is_expected_kind: fn(&Target) -> bool,
) -> Option<&Target> {
let targets = self.targets();
let matches = targets
.iter()
.filter(|t| is_expected_kind(t))
.map(|t| (lev_distance(target, t.name()), t))
.filter(|&(d, _)| d < 4);
matches.min_by_key(|t| t.0).map(|t| t.1)
}
pub fn map_source(self, to_replace: SourceId, replace_with: SourceId) -> Package { pub fn map_source(self, to_replace: SourceId, replace_with: SourceId) -> Package {
Package { Package {
manifest: self.manifest.map_source(to_replace, replace_with), manifest: self.manifest.map_source(to_replace, replace_with),

View File

@ -7,9 +7,8 @@ use crate::core::compiler::CompileMode;
use crate::core::interning::InternedString; use crate::core::interning::InternedString;
use crate::core::{Features, PackageId, PackageIdSpec, PackageSet, Shell}; use crate::core::{Features, PackageId, PackageIdSpec, PackageSet, Shell};
use crate::util::errors::CargoResultExt; use crate::util::errors::CargoResultExt;
use crate::util::lev_distance::lev_distance;
use crate::util::toml::{ProfilePackageSpec, StringOrBool, TomlProfile, TomlProfiles, U32OrBool}; use crate::util::toml::{ProfilePackageSpec, StringOrBool, TomlProfile, TomlProfiles, U32OrBool};
use crate::util::{CargoResult, Config}; use crate::util::{closest_msg, CargoResult, Config};
/// Collection of all user profiles. /// Collection of all user profiles.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -290,23 +289,12 @@ impl ProfileMaker {
}) })
.collect(); .collect();
if name_matches.is_empty() { if name_matches.is_empty() {
let suggestion = packages let suggestion =
.package_ids() closest_msg(&spec.name(), packages.package_ids(), |p| p.name().as_str());
.map(|p| (lev_distance(&*spec.name(), &p.name()), p.name())) shell.warn(format!(
.filter(|&(d, _)| d < 4) "profile override spec `{}` did not match any packages{}",
.min_by_key(|p| p.0) spec, suggestion
.map(|p| p.1); ))?;
match suggestion {
Some(p) => shell.warn(format!(
"profile override spec `{}` did not match any packages\n\n\
Did you mean `{}`?",
spec, p
))?,
None => shell.warn(format!(
"profile override spec `{}` did not match any packages",
spec
))?,
}
} else { } else {
shell.warn(format!( shell.warn(format!(
"version or URL in profile override spec `{}` does not \ "version or URL in profile override spec `{}` does not \

View File

@ -35,7 +35,7 @@ use crate::core::{Package, Target};
use crate::core::{PackageId, PackageIdSpec, TargetKind, Workspace}; use crate::core::{PackageId, PackageIdSpec, TargetKind, Workspace};
use crate::ops; use crate::ops;
use crate::util::config::Config; use crate::util::config::Config;
use crate::util::{lev_distance, profile, CargoResult}; use crate::util::{closest_msg, profile, CargoResult};
/// Contains information about how a package should be compiled. /// Contains information about how a package should be compiled.
#[derive(Debug)] #[derive(Debug)]
@ -906,26 +906,18 @@ fn find_named_targets<'a>(
let filter = |t: &Target| t.name() == target_name && is_expected_kind(t); let filter = |t: &Target| t.name() == target_name && is_expected_kind(t);
let proposals = filter_targets(packages, filter, true, mode); let proposals = filter_targets(packages, filter, true, mode);
if proposals.is_empty() { if proposals.is_empty() {
let suggestion = packages let targets = packages.iter().flat_map(|pkg| {
.iter() pkg.targets()
.flat_map(|pkg| { .iter()
pkg.targets() .filter(|target| is_expected_kind(target))
.iter() });
.filter(|target| is_expected_kind(target)) let suggestion = closest_msg(target_name, targets, |t| t.name());
}) failure::bail!(
.map(|target| (lev_distance(target_name, target.name()), target)) "no {} target named `{}`{}",
.filter(|&(d, _)| d < 4) target_desc,
.min_by_key(|t| t.0) target_name,
.map(|t| t.1); suggestion
match suggestion { );
Some(s) => failure::bail!(
"no {} target named `{}`\n\nDid you mean `{}`?",
target_desc,
target_name,
s.name()
),
None => failure::bail!("no {} target named `{}`", target_desc, target_name),
}
} }
Ok(proposals) Ok(proposals)
} }

View File

@ -2,7 +2,7 @@ use std::ffi::OsString;
use std::iter; use std::iter;
use std::path::Path; use std::path::Path;
use crate::core::{nightly_features_allowed, TargetKind, Workspace}; use crate::core::{TargetKind, Workspace};
use crate::ops; use crate::ops;
use crate::util::{CargoResult, ProcessError}; use crate::util::{CargoResult, ProcessError};
@ -55,22 +55,13 @@ pub fn run(
.into_iter() .into_iter()
.map(|(_pkg, target)| target.name()) .map(|(_pkg, target)| target.name())
.collect(); .collect();
if nightly_features_allowed() { failure::bail!(
failure::bail!( "`cargo run` could not determine which binary to run. \
"`cargo run` could not determine which binary to run. \ Use the `--bin` option to specify a binary, \
Use the `--bin` option to specify a binary, \ or the `default-run` manifest key.\n\
or (on nightly) the `default-run` manifest key.\n\ available binaries: {}",
available binaries: {}", names.join(", ")
names.join(", ") )
)
} else {
failure::bail!(
"`cargo run` requires that a package only have one \
executable; use the `--bin` option to specify which one \
to run\navailable binaries: {}",
names.join(", ")
)
}
} else { } else {
failure::bail!( failure::bail!(
"`cargo run` can run at most one executable, but \ "`cargo run` can run at most one executable, but \

View File

@ -514,10 +514,10 @@ pub enum CommandInfo {
} }
impl CommandInfo { impl CommandInfo {
pub fn name(&self) -> String { pub fn name(&self) -> &str {
match self { match self {
CommandInfo::BuiltIn { name, .. } => name.to_string(), CommandInfo::BuiltIn { name, .. } => &name,
CommandInfo::External { name, .. } => name.to_string(), CommandInfo::External { name, .. } => &name,
} }
} }
} }

View File

@ -33,6 +33,34 @@ pub fn lev_distance(me: &str, t: &str) -> usize {
dcol[t_last + 1] dcol[t_last + 1]
} }
/// Find the closest element from `iter` matching `choice`. The `key` callback
/// is used to select a `&str` from the iterator to compare against `choice`.
pub fn closest<'a, T>(
choice: &str,
iter: impl Iterator<Item = T>,
key: impl Fn(&T) -> &'a str,
) -> Option<T> {
// Only consider candidates with a lev_distance of 3 or less so we don't
// suggest out-of-the-blue options.
iter.map(|e| (lev_distance(choice, key(&e)), e))
.filter(|&(d, _)| d < 4)
.min_by_key(|t| t.0)
.map(|t| t.1)
}
/// Version of `closest` that returns a common "suggestion" that can be tacked
/// onto the end of an error message.
pub fn closest_msg<'a, T>(
choice: &str,
iter: impl Iterator<Item = T>,
key: impl Fn(&T) -> &'a str,
) -> String {
match closest(choice, iter, &key) {
Some(e) => format!("\n\n\tDid you mean `{}`?", key(&e)),
None => String::new(),
}
}
#[test] #[test]
fn test_lev_distance() { fn test_lev_distance() {
use std::char::{from_u32, MAX}; use std::char::{from_u32, MAX};

View File

@ -12,7 +12,7 @@ pub use self::graph::Graph;
pub use self::hex::{hash_u64, short_hash, to_hex}; pub use self::hex::{hash_u64, short_hash, to_hex};
pub use self::into_url::IntoUrl; pub use self::into_url::IntoUrl;
pub use self::into_url_with_base::IntoUrlWithBase; pub use self::into_url_with_base::IntoUrlWithBase;
pub use self::lev_distance::lev_distance; pub use self::lev_distance::{closest, closest_msg, lev_distance};
pub use self::lockserver::{LockServer, LockServerClient, LockServerStarted}; pub use self::lockserver::{LockServer, LockServerClient, LockServerStarted};
pub use self::paths::{bytes2path, dylib_path, join_paths, path2bytes}; pub use self::paths::{bytes2path, dylib_path, join_paths, path2bytes};
pub use self::paths::{dylib_path_envvar, normalize_path}; pub use self::paths::{dylib_path_envvar, normalize_path};

View File

@ -21,8 +21,7 @@ use crate::core::{Edition, EitherManifest, Feature, Features, VirtualManifest};
use crate::core::{GitReference, PackageIdSpec, SourceId, WorkspaceConfig, WorkspaceRootConfig}; use crate::core::{GitReference, PackageIdSpec, SourceId, WorkspaceConfig, WorkspaceRootConfig};
use crate::sources::{CRATES_IO_INDEX, CRATES_IO_REGISTRY}; use crate::sources::{CRATES_IO_INDEX, CRATES_IO_REGISTRY};
use crate::util::errors::{CargoResult, CargoResultExt, ManifestError}; use crate::util::errors::{CargoResult, CargoResultExt, ManifestError};
use crate::util::paths; use crate::util::{self, paths, validate_package_name, Config, IntoUrl};
use crate::util::{self, validate_package_name, Config, IntoUrl};
mod targets; mod targets;
use self::targets::targets; use self::targets::targets;
@ -1052,6 +1051,18 @@ impl TomlManifest {
) )
} }
if let Some(run) = &project.default_run {
if !targets
.iter()
.filter(|t| t.is_bin())
.any(|t| t.name() == run)
{
let suggestion =
util::closest_msg(&run, targets.iter().filter(|t| t.is_bin()), |t| t.name());
bail!("default-run target `{}` not found{}", run, suggestion);
}
}
let custom_metadata = project.metadata.clone(); let custom_metadata = project.metadata.clone();
let mut manifest = Manifest::new( let mut manifest = Manifest::new(
summary, summary,

View File

@ -29,7 +29,8 @@ include::options-package.adoc[]
When no target selection options are given, `cargo run` will run the binary When no target selection options are given, `cargo run` will run the binary
target. If there are multiple binary targets, you must pass a target flag to target. If there are multiple binary targets, you must pass a target flag to
choose one. choose one. Or, the `default-run` field may be specified in the `[package]`
section of `Cargo.toml` to choose the name of the binary to run by default.
*--bin* _NAME_:: *--bin* _NAME_::
Run the specified binary. Run the specified binary.

View File

@ -48,7 +48,8 @@ the SPEC format.</p>
<div class="paragraph"> <div class="paragraph">
<p>When no target selection options are given, <code>cargo run</code> will run the binary <p>When no target selection options are given, <code>cargo run</code> will run the binary
target. If there are multiple binary targets, you must pass a target flag to target. If there are multiple binary targets, you must pass a target flag to
choose one.</p> choose one. Or, the <code>default-run</code> field may be specified in the <code>[package]</code>
section of <code>Cargo.toml</code> to choose the name of the binary to run by default.</p>
</div> </div>
<div class="dlist"> <div class="dlist">
<dl> <dl>

View File

@ -21,7 +21,7 @@ when listed as a dependency in another package, and as the default name of
inferred lib and bin targets. inferred lib and bin targets.
The name must not be empty, use only [alphanumeric] characters or `-` or `_`. The name must not be empty, use only [alphanumeric] characters or `-` or `_`.
Note that `cargo new` and `cargo init` impose some additional restrictions on Note that [`cargo new`] and [`cargo init`] impose some additional restrictions on
the package name, such as enforcing that it is a valid Rust identifier and not the package name, such as enforcing that it is a valid Rust identifier and not
a keyword. [crates.io][cratesio] imposes even more restrictions, such as a keyword. [crates.io][cratesio] imposes even more restrictions, such as
enforcing only ASCII characters, not a reserved name, not a special Windows enforcing only ASCII characters, not a reserved name, not a special Windows
@ -66,7 +66,7 @@ edition = '2018'
``` ```
The `edition` key affects which edition your package is compiled with. Cargo The `edition` key affects which edition your package is compiled with. Cargo
will always generate packages via `cargo new` with the `edition` key set to the will always generate packages via [`cargo new`] with the `edition` key set to the
latest edition. Setting the `edition` key in `[package]` will affect all latest edition. Setting the `edition` key in `[package]` will affect all
targets/crates in the package, including test suites, benchmarks, binaries, targets/crates in the package, including test suites, benchmarks, binaries,
examples, etc. examples, etc.
@ -364,6 +364,17 @@ package-name = "my-awesome-android-app"
assets = "path/to/static" assets = "path/to/static"
``` ```
#### The `default-run` field
The `default-run` field in the `[package]` section of the manifest can be used
to specify a default binary picked by [`cargo run`]. For example, when there is
both `src/bin/a.rs` and `src/bin/b.rs`:
```toml
[package]
default-run = "a"
```
### Dependency sections ### Dependency sections
See the [specifying dependencies page](reference/specifying-dependencies.html) for See the [specifying dependencies page](reference/specifying-dependencies.html) for
@ -629,8 +640,8 @@ A crate may either specify `package.workspace` or specify `[workspace]`. That
is, a crate cannot both be a root crate in a workspace (contain `[workspace]`) is, a crate cannot both be a root crate in a workspace (contain `[workspace]`)
and also be a member crate of another workspace (contain `package.workspace`). and also be a member crate of another workspace (contain `package.workspace`).
Most of the time workspaces will not need to be dealt with as `cargo new` and Most of the time workspaces will not need to be dealt with as [`cargo new`] and
`cargo init` will handle workspace configuration automatically. [`cargo init`] will handle workspace configuration automatically.
[globs]: https://docs.rs/glob/0.2.11/glob/struct.Pattern.html [globs]: https://docs.rs/glob/0.2.11/glob/struct.Pattern.html
@ -643,7 +654,7 @@ manifest*.
#### Package selection #### Package selection
In a workspace, package-related cargo commands like `cargo build` apply to In a workspace, package-related cargo commands like [`cargo build`] apply to
packages selected by `-p` / `--package` or `--all` command-line parameters. packages selected by `-p` / `--package` or `--all` command-line parameters.
When neither is specified, the optional `default-members` configuration is used: When neither is specified, the optional `default-members` configuration is used:
@ -733,7 +744,7 @@ You can build individual library examples with the command `cargo build
### Tests ### Tests
When you run `cargo test`, Cargo will: When you run [`cargo test`], Cargo will:
* compile and run your librarys unit tests, which are in the files reachable * compile and run your librarys unit tests, which are in the files reachable
from `lib.rs` (naturally, any sections marked with `#[cfg(test)]` will be from `lib.rs` (naturally, any sections marked with `#[cfg(test)]` will be
@ -745,7 +756,7 @@ When you run `cargo test`, Cargo will:
#### Integration tests #### Integration tests
Each file in `tests/*.rs` is an integration test. When you run `cargo test`, Each file in `tests/*.rs` is an integration test. When you run [`cargo test`],
Cargo will compile each of these files as a separate crate. The crate can link Cargo will compile each of these files as a separate crate. The crate can link
to your library by using `extern crate <library-name>`, like any other code that to your library by using `extern crate <library-name>`, like any other code that
depends on it. depends on it.
@ -966,6 +977,11 @@ source (e.g., git or a local path).
More information about overriding dependencies can be found in the [overriding More information about overriding dependencies can be found in the [overriding
dependencies][replace] section of the documentation. dependencies][replace] section of the documentation.
[`cargo build`]: commands/cargo-build.html
[`cargo init`]: commands/cargo-init.html
[`cargo new`]: commands/cargo-new.html
[`cargo run`]: commands/cargo-run.html
[`cargo test`]: commands/cargo-test.html
[spdx-2.1-license-expressions]: https://spdx.org/spdx-specification-21-web-version#h.jxpfx0ykyb60 [spdx-2.1-license-expressions]: https://spdx.org/spdx-specification-21-web-version#h.jxpfx0ykyb60
[spdx-license-list]: https://spdx.org/licenses/
[spdx-license-list-2.4]: https://github.com/spdx/license-list-data/tree/v2.4 [spdx-license-list-2.4]: https://github.com/spdx/license-list-data/tree/v2.4
[spdx-license-list]: https://spdx.org/licenses/

View File

@ -155,18 +155,6 @@ Example:
cargo +nightly build --build-plan -Z unstable-options cargo +nightly build --build-plan -Z unstable-options
``` ```
### default-run
* Original issue: [#2200](https://github.com/rust-lang/cargo/issues/2200)
The `default-run` option in the `[package]` section of the manifest can be used
to specify a default binary picked by `cargo run`. For example, when there is
both `src/bin/a.rs` and `src/bin/b.rs`:
```toml
[package]
default-run = "a"
```
### Metabuild ### Metabuild
* Tracking Issue: [rust-lang/rust#49803](https://github.com/rust-lang/rust/issues/49803) * Tracking Issue: [rust-lang/rust#49803](https://github.com/rust-lang/rust/issues/49803)
* RFC: [#2196](https://github.com/rust-lang/rfcs/blob/master/text/2196-metabuild.md) * RFC: [#2196](https://github.com/rust-lang/rfcs/blob/master/text/2196-metabuild.md)

View File

@ -2,12 +2,12 @@
.\" Title: cargo-run .\" Title: cargo-run
.\" Author: [see the "AUTHOR(S)" section] .\" Author: [see the "AUTHOR(S)" section]
.\" Generator: Asciidoctor 1.5.8 .\" Generator: Asciidoctor 1.5.8
.\" Date: 2019-05-08 .\" Date: 2019-06-21
.\" Manual: \ \& .\" Manual: \ \&
.\" Source: \ \& .\" Source: \ \&
.\" Language: English .\" Language: English
.\" .\"
.TH "CARGO\-RUN" "1" "2019-05-08" "\ \&" "\ \&" .TH "CARGO\-RUN" "1" "2019-06-21" "\ \&" "\ \&"
.ie \n(.g .ds Aq \(aq .ie \n(.g .ds Aq \(aq
.el .ds Aq ' .el .ds Aq '
.ss \n[.ss] 0 .ss \n[.ss] 0
@ -54,7 +54,8 @@ the SPEC format.
.sp .sp
When no target selection options are given, \fBcargo run\fP will run the binary When no target selection options are given, \fBcargo run\fP will run the binary
target. If there are multiple binary targets, you must pass a target flag to target. If there are multiple binary targets, you must pass a target flag to
choose one. choose one. Or, the \fBdefault\-run\fP field may be specified in the \fB[package]\fP
section of \fBCargo.toml\fP to choose the name of the binary to run by default.
.sp .sp
\fB\-\-bin\fP \fINAME\fP \fB\-\-bin\fP \fINAME\fP
.RS 4 .RS 4

View File

@ -936,7 +936,7 @@ fn cargo_compile_with_filename() {
"\ "\
[ERROR] no bin target named `a.rs` [ERROR] no bin target named `a.rs`
Did you mean `a`?", <tab>Did you mean `a`?",
) )
.run(); .run();
@ -951,7 +951,7 @@ Did you mean `a`?",
"\ "\
[ERROR] no example target named `a.rs` [ERROR] no example target named `a.rs`
Did you mean `a`?", <tab>Did you mean `a`?",
) )
.run(); .run();
} }
@ -4417,7 +4417,7 @@ fn target_filters_workspace() {
"\ "\
[ERROR] no example target named `ex` [ERROR] no example target named `ex`
Did you mean `ex1`?", <tab>Did you mean `ex1`?",
) )
.run(); .run();

View File

@ -141,7 +141,7 @@ fn profile_override_warnings() {
[WARNING] version or URL in profile override spec `bar:1.2.3` does not match any of the packages: bar v0.5.0 ([..]) [WARNING] version or URL in profile override spec `bar:1.2.3` does not match any of the packages: bar v0.5.0 ([..])
[WARNING] profile override spec `bart` did not match any packages [WARNING] profile override spec `bart` did not match any packages
Did you mean `bar`? <tab>Did you mean `bar`?
[WARNING] profile override spec `no-suggestion` did not match any packages [WARNING] profile override spec `no-suggestion` did not match any packages
[COMPILING] [..] [COMPILING] [..]
", ",

View File

@ -1154,8 +1154,8 @@ fn run_default_multiple_required_features() {
.with_status(101) .with_status(101)
.with_stderr( .with_stderr(
"\ "\
error: `cargo run` requires that a package only have one executable; \ error: `cargo run` could not determine which binary to run[..]
use the `--bin` option to specify which one to run\navailable binaries: foo1, foo2", available binaries: foo1, foo2",
) )
.run(); .run();
} }

View File

@ -168,22 +168,11 @@ fn too_many_bins() {
// Using [..] here because the order is not stable // Using [..] here because the order is not stable
p.cargo("run") p.cargo("run")
.with_status(101)
.with_stderr(
"[ERROR] `cargo run` requires that a package only \
have one executable; use the `--bin` option \
to specify which one to run\navailable binaries: [..]\n",
)
.run();
// Using [..] here because the order is not stable
p.cargo("run")
.masquerade_as_nightly_cargo()
.with_status(101) .with_status(101)
.with_stderr( .with_stderr(
"[ERROR] `cargo run` could not determine which binary to run. \ "[ERROR] `cargo run` could not determine which binary to run. \
Use the `--bin` option to specify a binary, or (on \ Use the `--bin` option to specify a binary, or the \
nightly) the `default-run` manifest key.\ `default-run` manifest key.\
\navailable binaries: [..]\n", \navailable binaries: [..]\n",
) )
.run(); .run();
@ -241,8 +230,6 @@ fn specify_default_run() {
.file( .file(
"Cargo.toml", "Cargo.toml",
r#" r#"
cargo-features = ["default-run"]
[project] [project]
name = "foo" name = "foo"
version = "0.0.1" version = "0.0.1"
@ -255,18 +242,9 @@ fn specify_default_run() {
.file("src/bin/b.rs", r#"fn main() { println!("hello B"); }"#) .file("src/bin/b.rs", r#"fn main() { println!("hello B"); }"#)
.build(); .build();
p.cargo("run") p.cargo("run").with_stdout("hello A").run();
.masquerade_as_nightly_cargo() p.cargo("run --bin a").with_stdout("hello A").run();
.with_stdout("hello A") p.cargo("run --bin b").with_stdout("hello B").run();
.run();
p.cargo("run --bin a")
.masquerade_as_nightly_cargo()
.with_stdout("hello A")
.run();
p.cargo("run --bin b")
.masquerade_as_nightly_cargo()
.with_stdout("hello B")
.run();
} }
#[cargo_test] #[cargo_test]
@ -275,8 +253,6 @@ fn bogus_default_run() {
.file( .file(
"Cargo.toml", "Cargo.toml",
r#" r#"
cargo-features = ["default-run"]
[project] [project]
name = "foo" name = "foo"
version = "0.0.1" version = "0.0.1"
@ -288,61 +264,17 @@ fn bogus_default_run() {
.file("src/bin/a.rs", r#"fn main() { println!("hello A"); }"#) .file("src/bin/a.rs", r#"fn main() { println!("hello A"); }"#)
.build(); .build();
p.cargo("run")
.masquerade_as_nightly_cargo()
.with_status(101)
.with_stderr("error: no bin target named `b`\n\nDid you mean [..]?")
.run();
}
#[cargo_test]
fn default_run_unstable() {
let p = project()
.file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.0.1"
authors = []
default-run = "a"
"#,
)
.file("src/bin/a.rs", r#"fn main() { println!("hello A"); }"#)
.build();
p.cargo("run") p.cargo("run")
.with_status(101) .with_status(101)
.with_stderr( .with_stderr(
r#"error: failed to parse manifest at [..] "\
[ERROR] failed to parse manifest at `[..]/foo/Cargo.toml`
Caused by: Caused by:
the `default-run` manifest key is unstable default-run target `b` not found
Caused by: <tab>Did you mean `a`?
feature `default-run` is required ",
this Cargo does not support nightly features, but if you
switch to nightly channel you can add
`cargo-features = ["default-run"]` to enable this feature
"#,
)
.run();
p.cargo("run")
.masquerade_as_nightly_cargo()
.with_status(101)
.with_stderr(
r#"error: failed to parse manifest at [..]
Caused by:
the `default-run` manifest key is unstable
Caused by:
feature `default-run` is required
consider adding `cargo-features = ["default-run"]` to the manifest
"#,
) )
.run(); .run();
} }
@ -586,7 +518,7 @@ fn run_with_filename() {
"\ "\
[ERROR] no bin target named `a.rs` [ERROR] no bin target named `a.rs`
Did you mean `a`?", <tab>Did you mean `a`?",
) )
.run(); .run();
@ -601,7 +533,7 @@ Did you mean `a`?",
"\ "\
[ERROR] no example target named `a.rs` [ERROR] no example target named `a.rs`
Did you mean `a`?", <tab>Did you mean `a`?",
) )
.run(); .run();
} }
@ -1103,7 +1035,7 @@ fn run_workspace() {
.with_status(101) .with_status(101)
.with_stderr( .with_stderr(
"\ "\
[ERROR] `cargo run` requires that a package only have one executable[..] [ERROR] `cargo run` could not determine which binary to run[..]
available binaries: a, b", available binaries: a, b",
) )
.run(); .run();
@ -1123,8 +1055,6 @@ fn default_run_workspace() {
.file( .file(
"a/Cargo.toml", "a/Cargo.toml",
r#" r#"
cargo-features = ["default-run"]
[project] [project]
name = "a" name = "a"
version = "0.0.1" version = "0.0.1"
@ -1136,10 +1066,7 @@ fn default_run_workspace() {
.file("b/src/main.rs", r#"fn main() {println!("run-b");}"#) .file("b/src/main.rs", r#"fn main() {println!("run-b");}"#)
.build(); .build();
p.cargo("run") p.cargo("run").with_stdout("run-a").run();
.masquerade_as_nightly_cargo()
.with_stdout("run-a")
.run();
} }
#[cargo_test] #[cargo_test]