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
use anyhow::Result;
use super::super::cmd;
use super::super::errors;
use super::super::model;
use super::super::query;
pub fn main(app: &mut model::ApplicationContext) -> Result<()> {
let mut query = String::new();
let mut command: Vec<String> = Vec::new();
parse_args(&mut app.options, &mut query, &mut command);
let quiet = app.options.quiet;
let verbose = app.options.verbose;
let config = app.get_root_config_mut();
exec(config, quiet, verbose, &query, &command)
}
fn parse_args(options: &mut model::CommandOptions, query: &mut String, command: &mut Vec<String>) {
let mut ap = argparse::ArgumentParser::new();
ap.silence_double_dash(false);
ap.stop_on_first_argument(true);
ap.set_description("garden exec - run commands inside gardens");
ap.refer(query).required().add_argument(
"query",
argparse::Store,
"gardens/groups/trees to exec (tree query)",
);
ap.refer(command).required().add_argument(
"command",
argparse::List,
"command to run over resolved trees",
);
options.args.insert(0, "garden exec".into());
cmd::parse_args(ap, options.args.to_vec());
if options.is_debug("exec") {
debug!("command: exec");
debug!("query: {}", query);
debug!("command: {:?}", command);
}
}
pub fn exec(
config: &mut model::Configuration,
quiet: bool,
verbose: bool,
query: &str,
command: &[String],
) -> Result<()> {
let contexts = query::resolve_trees(config, query);
let mut exit_status: i32 = 0;
if command.is_empty() {
return Err(
errors::GardenError::Usage("a command to execute must be specified".into()).into(),
);
}
for context in &contexts {
if config.trees[context.tree].is_symlink {
continue;
}
if let Err(errors::GardenError::ExitStatus(status)) =
cmd::exec_in_context(config, context, quiet, verbose, command)
{
exit_status = status;
}
}
cmd::result_from_exit_status(exit_status).map_err(|err| err.into())
}