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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use clap::{ArgMatches, Command};
use crate::{
cli::{
errors,
validator::{validate_flight_name, validate_name_id},
CliCommand,
},
context::Ctx,
error::{CliErrorKind, Result},
};
#[derive(Copy, Clone, Debug)]
pub struct SeaplaneFlightDelete;
impl SeaplaneFlightDelete {
pub fn command() -> Command {
let validator = |s: &str| validate_name_id(validate_flight_name, s);
Command::new("delete")
.visible_aliases(["del", "remove", "rm"])
.about("Delete a local Flight Plan")
.arg(arg!(flight required =["NAME|ID"])
.value_parser(validator)
.help("The name or ID of the Flight Plan to remove, must be unambiguous"))
.arg(arg!(--force -('f'))
.help("Delete this Flight Plan even if referenced by a local Formation Plan, or deletes ALL Flight Plan referenced by the name or ID even if ambiguous"))
.arg(arg!(--all -('a'))
.help("Delete all matching Flight Plans even when the name or ID is ambiguous"))
}
}
impl CliCommand for SeaplaneFlightDelete {
fn run(&self, ctx: &mut Ctx) -> Result<()> {
if ctx.args.stateless {
cli_eprint!(@Red, "error: ");
cli_eprint!("'");
cli_eprint!(@Yellow, "--stateless");
cli_eprint!("' cannot be used with '");
cli_eprint!(@Yellow, "seaplane flight delete");
cli_eprintln!("'");
cli_eprintln!("(hint: 'seaplane flight delete' only modifies local plans)");
cli_eprint!("(hint: you may want 'seaplane ");
cli_eprint!(@Green, "formation ");
cli_eprintln!("delete' instead)");
std::process::exit(1);
}
let indices = if ctx.args.all {
ctx.db
.flights
.indices_of_left_matches(ctx.args.name_id.as_ref().unwrap())
} else {
ctx.db
.flights
.indices_of_matches(ctx.args.name_id.as_ref().unwrap())
};
match indices.len() {
0 => errors::no_matching_item(ctx.args.name_id.clone().unwrap(), false, ctx.args.all)?,
1 => (),
_ => {
if !(ctx.args.all || ctx.args.force) {
errors::ambiguous_item(ctx.args.name_id.clone().unwrap(), true)?;
}
}
}
let flights_in_use: Vec<String> = ctx
.db
.flights
.iter()
.enumerate()
.filter(|(i, _)| indices.contains(i))
.filter_map(|(_, flight)| {
if ctx.db.formations.has_flight(flight.model.name()) {
Some(flight.model.name().to_owned())
} else {
None
}
})
.collect();
if !flights_in_use.is_empty() {
if !ctx.args.force {
return Err(CliErrorKind::FlightsInUse(flights_in_use).into_err());
}
for flight in flights_in_use {
ctx.db.formations.remove_flight(&flight);
}
ctx.persist_formations()?;
}
ctx.db
.flights
.remove_indices(&indices)
.iter()
.for_each(|flight| {
cli_println!("Deleted local Flight Plan {}", &flight.id.to_string());
});
ctx.persist_flights()?;
if !ctx.internal_run {
cli_println!(
"\nSuccessfully removed {} item{}",
indices.len(),
if indices.len() > 1 { "s" } else { "" }
);
}
Ok(())
}
fn update_ctx(&self, matches: &ArgMatches, ctx: &mut Ctx) -> Result<()> {
ctx.args.force = matches.get_flag("force");
ctx.args.all = matches.get_flag("all");
ctx.args.name_id = matches.get_one::<String>("flight").map(ToOwned::to_owned);
Ok(())
}
}