seaplane_cli/cli/cmds/formation/
fetch.rs1use std::collections::HashSet;
2
3use clap::{ArgMatches, Command};
4
5use crate::{api::FormationsReq, cli::CliCommand, error::Result, printer::Pb, Ctx};
6
7#[derive(Copy, Clone, Debug)]
8pub struct SeaplaneFormationFetch;
9
10impl SeaplaneFormationFetch {
11 pub fn command() -> Command {
12 Command::new("fetch-remote")
14 .visible_aliases(["fetch", "sync", "synchronize"])
15 .about("Fetch remote Formation Instances and create/synchronize local Plan definitions")
16 .override_usage("
17 seaplane formation fetch-remote
18 seaplane formation fetch-remote [NAME|ID]",
19 )
20 .arg(
21 arg!(formation = ["NAME|ID"])
22 .help("The NAME or ID of the remote Formation Instance to fetch, omit to fetch all Formation Instances"),
23 )
24 }
25}
26
27impl CliCommand for SeaplaneFormationFetch {
28 fn run(&self, ctx: &mut Ctx) -> Result<()> {
30 let pb = Pb::new(ctx);
31 pb.set_message("Gathering Formation Names...");
32
33 let mut req = FormationsReq::new_delay_token(ctx)?;
34 if let Some(name) = &ctx.args.name_id {
35 req.set_name(name)?;
36 }
37 let names = req.get_formation_names()?;
38
39 pb.set_message("Syncing Formations...");
40 let mut remote_instances = req.get_all_formations(&names, &pb)?;
46
47 let mut flights_added = HashSet::new();
49 let mut formations_added = HashSet::new();
50 let mut configs_updated = HashSet::new();
51
52 for formation in remote_instances.formations.iter_mut() {
54 for cfg in formation.configs().iter().filter_map(|id| {
56 if let Some(i) = remote_instances
58 .configurations
59 .iter()
60 .enumerate()
61 .find_map(|(i, cfg)| if &cfg.id == id { Some(i) } else { None })
62 {
63 Some(remote_instances.configurations.swap_remove(i))
67 } else {
68 None
69 }
70 }) {
71 for flight in cfg.model.flights() {
73 let names_ids = ctx.db.flights.update_or_create_flight(flight);
76 flights_added.extend(names_ids);
77 }
78
79 let old_id = cfg.id;
81 if let Some(real_id) = ctx.db.formations.update_or_create_configuration(cfg) {
84 formation.replace_id(&old_id, real_id);
85 configs_updated.insert((formation.name.clone().unwrap(), real_id));
86 }
87 }
88 if let Some(id) = ctx
91 .db
92 .formations
93 .update_or_create_formation(formation.clone())
94 {
95 formations_added.insert((formation.name.clone().unwrap(), id));
96 }
97 }
98
99 pb.finish_and_clear();
100
101 if !ctx.internal_run {
102 let mut count = 0;
103 for (name, id) in formations_added {
104 count += 1;
105 cli_print!("Successfully synchronized Formation Instance '");
106 cli_print!(@Green, "{name}");
107 cli_print!("' with local Formation ID '");
108 cli_print!(@Green, "{}", &id.to_string()[..8]);
109 cli_println!("'");
110 }
111 for (name, id) in configs_updated {
112 count += 1;
113 cli_print!("Successfully synchronized Formation Configuration in Formation '");
114 cli_print!(@Green, "{name}");
115 cli_print!("' with local Formation Configuration ID '");
116 cli_print!(@Green, "{}", &id.to_string()[..8]);
117 cli_println!("'");
118 }
119 for (name, id) in flights_added {
120 count += 1;
121 cli_print!("Successfully synchronized Flight Plan '");
122 cli_print!(@Green, "{name}");
123 cli_print!("' with local Flight Plan ID '");
124 cli_print!(@Green, "{}", &id.to_string()[..8]);
125 cli_println!("'!");
126 }
127 if names.is_empty() {
128 cli_println!("No remote Formation Instances found");
129 } else if count > 0 {
130 cli_println!("");
131 cli_println!("Successfully fetched {count} items");
132 } else {
133 cli_println!("All local definitions are up to date!");
134 }
135 }
136
137 ctx.persist_flights()?;
138 ctx.persist_formations()?;
139
140 Ok(())
141 }
142
143 fn update_ctx(&self, matches: &ArgMatches, ctx: &mut Ctx) -> Result<()> {
144 ctx.args.name_id = matches
145 .get_one::<String>("formation")
146 .map(ToOwned::to_owned);
147 Ok(())
148 }
149}