arm_toolchain/cli/
remove.rs1use futures::future::try_join_all;
2use humansize::DECIMAL;
3use indicatif::{MultiProgress, ProgressBar};
4use tokio_util::sync::CancellationToken;
5
6use crate::{
7 cli::{CliError, PROGRESS_STYLE_DELETE, PROGRESS_STYLE_DELETE_SPINNER, ctrl_c_cancel, msg},
8 toolchain::{RemoveProgress, ToolchainClient, ToolchainError, ToolchainVersion},
9};
10
11#[derive(Debug, clap::Parser)]
13pub struct RemoveArgs {
14 pub version: ToolchainVersion,
16}
17
18pub async fn remove(args: RemoveArgs) -> Result<(), CliError> {
20 let client = ToolchainClient::using_data_dir().await?;
21 let toolchains = client.installed_versions().await?;
22
23 if args.version.name == "all" {
24 let old_active = client.active_toolchain();
25 client.set_active_toolchain(None).await?;
26
27 if toolchains.is_empty() && old_active.is_none() {
28 return Err(CliError::NoToolchainEnabled);
29 }
30
31 let cancel_token = ctrl_c_cancel();
32 let multi_progress = MultiProgress::new();
33 let mut futs = vec![];
34
35 for version in toolchains {
36 let client = client.clone();
37 let tok = cancel_token.clone();
38 let multi_progress = multi_progress.clone();
39
40 futs.push(remove_with_progress_bar(
41 client,
42 version,
43 tok,
44 multi_progress,
45 ));
46 }
47
48 let out = try_join_all(futs).await?;
49 let total_bytes = out.iter().sum::<u64>();
50
51 println!(
52 "Removed {} toolchains ({})",
53 out.len(),
54 humansize::format_size(total_bytes, DECIMAL),
55 );
56
57 cancel_token.cancel();
58 } else {
59 if !toolchains.contains(&args.version) {
60 return Err(CliError::CannotRemoveMissingToolchain {
61 version: args.version,
62 });
63 }
64
65 let cancel_token = ctrl_c_cancel();
66 let multi = MultiProgress::new();
67 let bytes =
68 remove_with_progress_bar(client, args.version.clone(), cancel_token.clone(), multi)
69 .await?;
70
71 cancel_token.cancel();
72
73 msg!(
74 "Removed",
75 "{} ({})",
76 args.version,
77 humansize::format_size(bytes, DECIMAL),
78 );
79 }
80
81 Ok(())
82}
83
84async fn remove_with_progress_bar(
85 client: ToolchainClient,
86 version: ToolchainVersion,
87 cancel_token: CancellationToken,
88 multi_progress: MultiProgress,
89) -> Result<u64, ToolchainError> {
90 let bar = ProgressBar::no_length()
91 .with_style(PROGRESS_STYLE_DELETE_SPINNER.clone())
92 .with_message(format!("Removing {version}"));
93 multi_progress.add(bar.clone());
94
95 let progress = |status| match status {
96 RemoveProgress::Start { total_bytes } => {
97 bar.reset();
98 bar.set_length(total_bytes);
99 bar.set_style(PROGRESS_STYLE_DELETE.clone());
100 }
101 RemoveProgress::Progress { bytes_removed } => {
102 bar.set_position(bytes_removed);
103 }
104 RemoveProgress::End => {
105 bar.finish_with_message(format!("{version} is removed"));
106 }
107 };
108
109 client.remove(&version, progress, &cancel_token).await?;
110
111 Ok(bar.length().unwrap_or(0))
112}