please_install/
reinstall.rs

1use std::collections::BTreeMap;
2
3use eyre::{eyre, Result};
4
5use crate::package::Package;
6use crate::track::load_tracks;
7use crate::pls_command::PlsCommand;
8use crate::run_command::run_command;
9use crate::vendor_data::VendorData;
10use crate::vendors::Vendor;
11
12pub fn reinstall_all(
13    vendor: Option<Vendor>,
14    yes: bool,
15    su: bool,
16    dry_run: bool,
17    pager: &Option<String>,
18    pls_command: PlsCommand,
19) -> Result<i32> {
20    let tracks = tracks_by_vendor()?;
21    let mut status = 0;
22
23    for (v, packages) in tracks {
24        if let Some(vendor) = vendor {
25            if vendor != v {
26                continue;
27            }
28        }
29        let vendor_data: VendorData = v.try_into()?;
30        let command = PlsCommand::ReinstallAll.format(
31            vendor_data,
32            &packages,
33            yes,
34            pager,
35        );
36        if command.is_empty() {
37            continue;
38        }
39
40        if dry_run {
41            println!("{}", command);
42            continue;
43        }
44
45        let mut current = run_command(&command, su, &pager, pls_command)?;
46        if current != 0 {
47            current = rerun_reinstall_all_on_failure(vendor_data, yes, &pager, su, pls_command);
48        }
49
50        if current != 0 {
51            status = current;
52        }
53    }
54
55    Ok(status)
56}
57
58fn tracks_by_vendor() -> Result<BTreeMap<Vendor, Vec<Package>>> {
59    let mut res = BTreeMap::new();
60    let tracks = load_tracks()?;
61    if tracks.is_empty() {
62        return Err(eyre!("no known installed packages"));
63    }
64    for track in tracks {
65        res
66            .entry(track.vendor)
67            .or_insert(vec![])
68            .push(track.clone());
69    }
70    for (_, packages) in res.iter_mut() {
71        packages.sort();
72    }
73    Ok(res)
74}
75
76fn rerun_reinstall_all_on_failure(
77    vendor_data: VendorData,
78    yes: bool,
79    pager: &Option<String>,
80    su: bool,
81    pls_command: PlsCommand,
82) -> i32 {
83    let tracks = load_tracks().unwrap_or_default();
84    let mut response = 0;
85    for track in tracks {
86        let command = PlsCommand::Install.format(vendor_data, &vec![track], yes, pager);
87        match run_command(&command, su, pager, pls_command) {
88            Ok(status) => {
89                if status != 0 {
90                    response = status;
91                }
92            },
93            Err(err) => {
94                eprintln!("error running command: {}", err);
95                response = 1;
96            }
97        }
98    }
99    response
100}