-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
run.rs
112 lines (104 loc) · 3.82 KB
/
run.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use crate::command_prelude::*;
use crate::util::restricted_names::is_glob_pattern;
use cargo::core::Verbosity;
use cargo::ops::{self, CompileFilter, Packages};
use cargo_util::ProcessError;
pub fn cli() -> App {
subcommand("run")
// subcommand aliases are handled in aliased_command()
// .alias("r")
.setting(AppSettings::TrailingVarArg)
.about("Run a binary or example of the local package")
.arg_quiet()
.arg(
Arg::new("args")
.allow_invalid_utf8(true)
.multiple_values(true),
)
.arg_targets_bin_example(
"Name of the bin target to run",
"Name of the example target to run",
)
.arg_package("Package with the target to run")
.arg_jobs()
.arg_release("Build artifacts in release mode, with optimizations")
.arg_profile("Build artifacts with the specified profile")
.arg_features()
.arg_target_triple("Build for the target triple")
.arg_target_dir()
.arg_manifest_path()
.arg_message_format()
.arg_unit_graph()
.arg_ignore_rust_version()
.after_help("Run `cargo help run` for more detailed information.\n")
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
let ws = args.workspace(config)?;
let mut compile_opts = args.compile_options(
config,
CompileMode::Build,
Some(&ws),
ProfileChecking::Custom,
)?;
// Disallow `spec` to be an glob pattern
if let Packages::Packages(opt_in) = &compile_opts.spec {
if let Some(pattern) = opt_in.iter().find(|s| is_glob_pattern(s)) {
return Err(anyhow::anyhow!(
"`cargo run` does not support glob pattern `{}` on package selection",
pattern,
)
.into());
}
}
if !args.is_present("example") && !args.is_present("bin") {
let default_runs: Vec<_> = compile_opts
.spec
.get_packages(&ws)?
.iter()
.filter_map(|pkg| pkg.manifest().default_run())
.collect();
if default_runs.len() == 1 {
compile_opts.filter = CompileFilter::from_raw_arguments(
false,
vec![default_runs[0].to_owned()],
false,
vec![],
false,
vec![],
false,
vec![],
false,
false,
);
} else {
// ops::run will take care of errors if len pkgs != 1.
compile_opts.filter = CompileFilter::Default {
// Force this to false because the code in ops::run is not
// able to pre-check features before compilation starts to
// enforce that only 1 binary is built.
required_features_filterable: false,
};
}
};
ops::run(&ws, &compile_opts, &values_os(args, "args")).map_err(|err| {
let proc_err = match err.downcast_ref::<ProcessError>() {
Some(e) => e,
None => return CliError::new(err, 101),
};
// If we never actually spawned the process then that sounds pretty
// bad and we always want to forward that up.
let exit_code = match proc_err.code {
Some(exit) => exit,
None => return CliError::new(err, 101),
};
// If `-q` was passed then we suppress extra error information about
// a failed process, we assume the process itself printed out enough
// information about why it failed so we don't do so as well
let is_quiet = config.shell().verbosity() == Verbosity::Quiet;
if is_quiet {
CliError::code(exit_code)
} else {
CliError::new(err, exit_code)
}
})
}