From ccd108591fd333b915a405e7f61d47add29f0bfa Mon Sep 17 00:00:00 2001 From: innocentzero Date: Thu, 22 Feb 2024 02:26:04 +0530 Subject: [PATCH 01/18] feat(rustup): Add rustup as a backend Adds rustup as a backend for pacdef. Only works on components listed for now. Signed-off-by: innocentzero --- crates/pacdef_core/src/backend/actual/mod.rs | 1 + .../pacdef_core/src/backend/actual/rustup.rs | 69 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 crates/pacdef_core/src/backend/actual/rustup.rs diff --git a/crates/pacdef_core/src/backend/actual/mod.rs b/crates/pacdef_core/src/backend/actual/mod.rs index a30c8c1..36ad67e 100644 --- a/crates/pacdef_core/src/backend/actual/mod.rs +++ b/crates/pacdef_core/src/backend/actual/mod.rs @@ -5,3 +5,4 @@ pub mod debian; pub mod flatpak; pub mod python; pub mod rust; +pub mod rustup; diff --git a/crates/pacdef_core/src/backend/actual/rustup.rs b/crates/pacdef_core/src/backend/actual/rustup.rs new file mode 100644 index 0000000..682429b --- /dev/null +++ b/crates/pacdef_core/src/backend/actual/rustup.rs @@ -0,0 +1,69 @@ +use crate::backend::backend_trait::{Backend, Switches, Text}; +use crate::backend::macros::impl_backend_constants; +use crate::{Group, Package}; +use anyhow::Context; +use core::panic; +use std::collections::HashSet; +use std::process::Command; + +#[derive(Debug, Clone)] +pub struct Rustup { + pub(crate) packages: HashSet, +} + +const BINARY: Text = "rustup"; +const SECTION: Text = "rustup"; + +const SWITCHES_INSTALL: Switches = &["component", "add"]; +const SWITCHES_INFO: Switches = &["component", "list", "--installed"]; +const SWITCHES_MAKE_DEPENDENCY: Switches = &[]; +const SWITCHES_NOCONFIRM: Switches = &[]; +const SWITCHES_REMOVE: Switches = &["component", "remove"]; + +const SUPPORTS_AS_DEPENDENCY: bool = false; + +impl Backend for Rustup { + impl_backend_constants!(); + + fn get_all_installed_packages(&self) -> anyhow::Result> { + let mut cmd = Command::new(self.get_binary()); + let packages: HashSet = run_rustup_command(&mut cmd, SWITCHES_INFO) + .context("Getting installed components")? + .iter() + .map(|name| ["component/", name].join("").into()) + .collect(); + Ok(packages) + } + + fn get_explicitly_installed_packages(&self) -> anyhow::Result> { + self.get_all_installed_packages() + .context("Getting all installed packages") + } + + fn make_dependency(&self, _: &[Package]) -> anyhow::Result { + panic!("Not supported by {}", BINARY) + } +} + +fn run_rustup_command(cmd: &mut Command, args: &[&str]) -> Result, anyhow::Error> { + cmd.args(args); + let output = String::from_utf8(cmd.output()?.stdout)?; + let mut val = Vec::new(); + for i in output.lines() { + let mut it = i.splitn(3, "-"); + let component = it.next().expect("Component name is empty!"); + match component { + "cargo" | "rustfmt" | "clippy" | "miri" | "rls" | "rustc" => { + val.push(component.to_string()); + } + _ => { + val.push( + component.to_string() + + "-" + + it.next().expect("No such component is managed by rustup"), + ); + } + } + } + Ok(val) +} From 1ad93cec9695aebae6c4329b1f7a166e8d8e63fa Mon Sep 17 00:00:00 2001 From: innocentzero Date: Wed, 28 Feb 2024 00:39:31 +0530 Subject: [PATCH 02/18] refact(package.rs): Expose repo field publicly Expose repo field publicly for install_packages in rustup backend to utilize, otherwise very ugly hacks need to be used to handle toolchains and components. Signed-off-by: innocentzero --- crates/pacdef_core/src/grouping/package.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/pacdef_core/src/grouping/package.rs b/crates/pacdef_core/src/grouping/package.rs index f10b756..ed12a76 100644 --- a/crates/pacdef_core/src/grouping/package.rs +++ b/crates/pacdef_core/src/grouping/package.rs @@ -6,7 +6,7 @@ use std::hash::Hash; #[derive(Debug, Eq, PartialOrd, Ord, Clone)] pub struct Package { pub(crate) name: String, - repo: Option, + pub(crate) repo: Option, } fn remove_comment_and_trim_whitespace(s: &str) -> &str { @@ -41,10 +41,11 @@ impl Package { /// /// Panics if `string` is empty. fn split_into_name_and_repo(string: &str) -> (String, Option) { - let mut iter = string.split('/').rev(); - let name = iter.next().expect("we checked that earlier").to_string(); - let repo = iter.next().map(|s| s.to_string()); - (name, repo) + if let Some((before, after)) = string.split_once('/') { + (after.to_string(), Some(before.to_string())) + } else { + (string.to_string(), None) + } } /// Try to parse a string (from a line in a group file) and return a package. From d4551a6a2be945520891725c2ffd7945dce6afa6 Mon Sep 17 00:00:00 2001 From: innocentzero Date: Wed, 28 Feb 2024 00:47:19 +0530 Subject: [PATCH 03/18] feat(rustup): add rustup as a module --- crates/pacdef_core/src/backend/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/pacdef_core/src/backend/mod.rs b/crates/pacdef_core/src/backend/mod.rs index 7e39d3d..0664d7e 100644 --- a/crates/pacdef_core/src/backend/mod.rs +++ b/crates/pacdef_core/src/backend/mod.rs @@ -19,4 +19,5 @@ pub enum Backends { Flatpak, Python, Rust, + Rustup, } From ea2c51620a7cb0b52ae4929ce91daf39b3414255 Mon Sep 17 00:00:00 2001 From: innocentzero Date: Wed, 28 Feb 2024 00:56:24 +0530 Subject: [PATCH 04/18] refact(rustup): fetch installed toolchains and components Refactor the functions used for fetching installed components and toolchains. Signed-off-by: innocentzero --- .../pacdef_core/src/backend/actual/rustup.rs | 88 ++++++++++++++----- 1 file changed, 65 insertions(+), 23 deletions(-) diff --git a/crates/pacdef_core/src/backend/actual/rustup.rs b/crates/pacdef_core/src/backend/actual/rustup.rs index 682429b..8c57826 100644 --- a/crates/pacdef_core/src/backend/actual/rustup.rs +++ b/crates/pacdef_core/src/backend/actual/rustup.rs @@ -26,13 +26,26 @@ impl Backend for Rustup { impl_backend_constants!(); fn get_all_installed_packages(&self) -> anyhow::Result> { - let mut cmd = Command::new(self.get_binary()); - let packages: HashSet = run_rustup_command(&mut cmd, SWITCHES_INFO) + let mut toolchains_vec = self + .run_toolchain_command(&[&"toolchain", &"list"]) + .context("Getting installed toolchains")?; + + let mut toolchains: HashSet = toolchains_vec + .iter() + .map(|name| ["toolchain", name].join("/").into()) + .collect(); + + let packages: HashSet = self + .run_component_command( + &[&"component", &"list", &"--installed", &"--toolchain"], + &mut toolchains_vec, + ) .context("Getting installed components")? .iter() - .map(|name| ["component/", name].join("").into()) + .map(|name| ["component", name].join("/").into()) .collect(); - Ok(packages) + toolchains.extend(packages.into_iter()); + Ok(toolchains) } fn get_explicitly_installed_packages(&self) -> anyhow::Result> { @@ -43,27 +56,56 @@ impl Backend for Rustup { fn make_dependency(&self, _: &[Package]) -> anyhow::Result { panic!("Not supported by {}", BINARY) } -} -fn run_rustup_command(cmd: &mut Command, args: &[&str]) -> Result, anyhow::Error> { - cmd.args(args); - let output = String::from_utf8(cmd.output()?.stdout)?; - let mut val = Vec::new(); - for i in output.lines() { - let mut it = i.splitn(3, "-"); - let component = it.next().expect("Component name is empty!"); - match component { - "cargo" | "rustfmt" | "clippy" | "miri" | "rls" | "rustc" => { - val.push(component.to_string()); - } - _ => { - val.push( - component.to_string() - + "-" - + it.next().expect("No such component is managed by rustup"), - ); } + +impl Rustup { + pub(crate) fn new() -> Self { + Self { + packages: HashSet::new(), } } - Ok(val) + + fn run_component_command( + &self, + args: &[&str], + toolchains: &mut Vec, + ) -> Result, anyhow::Error> { + let mut val = Vec::new(); + for toolchain in toolchains { + let mut cmd = Command::new(self.get_binary()); + cmd.args(args); + cmd.arg(&toolchain); + let output = String::from_utf8(cmd.output()?.stdout)?; + for i in output.lines() { + let mut it = i.splitn(3, "-"); + let component = it.next().expect("Component name is empty!"); + match component { + "cargo" | "rustfmt" | "clippy" | "miri" | "rls" | "rustc" => { + val.push([toolchain, component].join("/")); + } + _ => { + let component = [ + component, + it.next().expect("No such component is managed by rustup"), + ] + .join("-"); + val.push([toolchain, component.as_str()].join("/")); + } + } + } + } + Ok(val) + } + fn run_toolchain_command(&self, args: &[&str]) -> Result, anyhow::Error> { + let mut cmd = Command::new(self.get_binary()); + cmd.args(args); + let output = String::from_utf8(cmd.output()?.stdout)?; + let mut val = Vec::new(); + for i in output.lines() { + let mut it = i.splitn(2, "-"); + val.push(it.next().expect("Toolchain name is empty.").to_string()); + } + Ok(val) + } } From fbedd6da49bee874f9ad21ac959e8597bc0fcbef Mon Sep 17 00:00:00 2001 From: innocentzero Date: Wed, 28 Feb 2024 01:04:01 +0530 Subject: [PATCH 05/18] feat(rustup): install packages Rustup is now able to install toolchains and components and works with multiple toolchains and components for each toolchain. Signed-off-by: innocentzero --- .../pacdef_core/src/backend/actual/rustup.rs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/crates/pacdef_core/src/backend/actual/rustup.rs b/crates/pacdef_core/src/backend/actual/rustup.rs index 8c57826..019300e 100644 --- a/crates/pacdef_core/src/backend/actual/rustup.rs +++ b/crates/pacdef_core/src/backend/actual/rustup.rs @@ -4,6 +4,7 @@ use crate::{Group, Package}; use anyhow::Context; use core::panic; use std::collections::HashSet; +use std::os::unix::process::ExitStatusExt; use std::process::Command; #[derive(Debug, Clone)] @@ -57,7 +58,50 @@ impl Backend for Rustup { panic!("Not supported by {}", BINARY) } + fn install_packages( + &self, + packages: &[Package], + _noconfirm: bool, + ) -> anyhow::Result { + let mut result: anyhow::Result = + Ok(std::process::ExitStatus::from_raw(0)); + for p in packages { + let repo = p + .repo + .as_ref() + .expect("Not specified whether it is a toolchain or a component!"); + if repo == "toolchain" { + let mut cmd = Command::new(self.get_binary()); + cmd.args(&[&"toolchain", &"install"]); + cmd.arg(format!("{}", p.name)); + result = cmd.status().context("Installing toolchain {p}"); + if !result.as_ref().is_ok_and(|exit| exit.success()) { + return result; + } + }; + } + for p in packages { + let repo = p + .repo + .as_ref() + .expect("Not specified wether it is a component or a toolchain!"); + if repo == "component" { + let mut iter = p.name.split('/'); + let toolchain = iter.next().expect("Toolchain not specified!"); + let component = iter.next().expect("Component not specified!"); + let mut cmd = Command::new(self.get_binary()); + cmd.args(&[&"component", &"add"]); + cmd.args([&"--toolchain", format!("{toolchain}").as_str()]); + cmd.arg(format!("{component}")); + result = cmd.status().context("Installing component {p}"); + if !result.as_ref().is_ok_and(|exit| exit.success()) { + return result; + } } + } + result + } +} impl Rustup { pub(crate) fn new() -> Self { From f9528241e7c83942be162981502f265e9a73c68d Mon Sep 17 00:00:00 2001 From: innocentzero Date: Wed, 28 Feb 2024 03:45:18 +0530 Subject: [PATCH 06/18] refact(rustup): Refector install_packages Signed-off-by: innocentzero --- .../pacdef_core/src/backend/actual/rustup.rs | 56 ++++++++++++++----- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/crates/pacdef_core/src/backend/actual/rustup.rs b/crates/pacdef_core/src/backend/actual/rustup.rs index 019300e..cc1ecb6 100644 --- a/crates/pacdef_core/src/backend/actual/rustup.rs +++ b/crates/pacdef_core/src/backend/actual/rustup.rs @@ -28,7 +28,7 @@ impl Backend for Rustup { fn get_all_installed_packages(&self) -> anyhow::Result> { let mut toolchains_vec = self - .run_toolchain_command(&[&"toolchain", &"list"]) + .run_toolchain_command(self.get_info_switches("toolchain")) .context("Getting installed toolchains")?; let mut toolchains: HashSet = toolchains_vec @@ -37,10 +37,7 @@ impl Backend for Rustup { .collect(); let packages: HashSet = self - .run_component_command( - &[&"component", &"list", &"--installed", &"--toolchain"], - &mut toolchains_vec, - ) + .run_component_command(self.get_info_switches("component"), &mut toolchains_vec) .context("Getting installed components")? .iter() .map(|name| ["component", name].join("/").into()) @@ -55,13 +52,13 @@ impl Backend for Rustup { } fn make_dependency(&self, _: &[Package]) -> anyhow::Result { - panic!("Not supported by {}", BINARY) + panic!("Not supported by {}", self.get_binary()) } fn install_packages( &self, packages: &[Package], - _noconfirm: bool, + _: bool, ) -> anyhow::Result { let mut result: anyhow::Result = Ok(std::process::ExitStatus::from_raw(0)); @@ -70,16 +67,29 @@ impl Backend for Rustup { .repo .as_ref() .expect("Not specified whether it is a toolchain or a component!"); - if repo == "toolchain" { - let mut cmd = Command::new(self.get_binary()); - cmd.args(&[&"toolchain", &"install"]); - cmd.arg(format!("{}", p.name)); - result = cmd.status().context("Installing toolchain {p}"); - if !result.as_ref().is_ok_and(|exit| exit.success()) { - return result; + let mut cmd = Command::new(self.get_binary()); + cmd.args(self.get_install_switches(repo)); + match repo.as_str() { + "toolchain" => { + cmd.arg(format!("{}", p.name)); } - }; + "component" => { + let mut iter = p.name.split('/'); + let toolchain = iter.next().expect("Toolchain not specified!"); + let component = iter.next().expect("Component not specified!"); + cmd.arg(format!("{toolchain}")); + cmd.arg(format!("{component}")); + } + _ => panic!("No such type is managed by rustup!"), + } + result = cmd.status().context("Installing toolchain {p}"); + if !result.as_ref().is_ok_and(|exit| exit.success()) { + return result; + } } + result + } + for p in packages { let repo = p .repo @@ -110,6 +120,22 @@ impl Rustup { } } + fn get_install_switches(&self, repotype: &str) -> Switches { + match repotype { + "toolchain" => &["toolchain", "install"], + "component" => &["component", "add", "--toolchain"], + _ => panic!("No such type managed by rust"), + } + } + + fn get_info_switches(&self, repotype: &str) -> Switches { + match repotype { + "toolchain" => &["toolchain", "list"], + "component" => &["component", "list", "--installed", "--toolchain"], + _ => panic!("No such type managed by rust"), + } + } + fn run_component_command( &self, args: &[&str], From 97b4077b02b95c10bb22a60b03f51769bd0fc10c Mon Sep 17 00:00:00 2001 From: innocentzero Date: Wed, 28 Feb 2024 03:45:52 +0530 Subject: [PATCH 07/18] feat(rustup): Remove packages Signed-off-by: innocentzero --- .../pacdef_core/src/backend/actual/rustup.rs | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/crates/pacdef_core/src/backend/actual/rustup.rs b/crates/pacdef_core/src/backend/actual/rustup.rs index cc1ecb6..2f63ddd 100644 --- a/crates/pacdef_core/src/backend/actual/rustup.rs +++ b/crates/pacdef_core/src/backend/actual/rustup.rs @@ -90,20 +90,23 @@ impl Backend for Rustup { result } + fn remove_packages( + &self, + packages: &[Package], + _: bool, + ) -> anyhow::Result { + let mut result: anyhow::Result = + Ok(std::process::ExitStatus::from_raw(0)); for p in packages { let repo = p .repo .as_ref() - .expect("Not specified wether it is a component or a toolchain!"); - if repo == "component" { - let mut iter = p.name.split('/'); - let toolchain = iter.next().expect("Toolchain not specified!"); - let component = iter.next().expect("Component not specified!"); + .expect("Not specified whether it is a toolchain or a component!"); + if repo == "toolchain" { let mut cmd = Command::new(self.get_binary()); - cmd.args(&[&"component", &"add"]); - cmd.args([&"--toolchain", format!("{toolchain}").as_str()]); - cmd.arg(format!("{component}")); - result = cmd.status().context("Installing component {p}"); + cmd.args(self.get_remove_switches(repo)); + cmd.arg(format!("{}", p.name)); + result = cmd.status().context("Removing toolchain {p}"); if !result.as_ref().is_ok_and(|exit| exit.success()) { return result; } @@ -128,6 +131,14 @@ impl Rustup { } } + fn get_remove_switches(&self, repotype: &str) -> Switches { + match repotype { + "toolchain" => &["toolchain", "uninstall"], + "component" => &["component", "remove", "--toolchain"], + _ => panic!("No such type managed by rust"), + } + } + fn get_info_switches(&self, repotype: &str) -> Switches { match repotype { "toolchain" => &["toolchain", "list"], From 4e2ef50df7291ee244983ca9fdf94bd5f9473e11 Mon Sep 17 00:00:00 2001 From: innocentzero Date: Wed, 28 Feb 2024 19:50:08 +0530 Subject: [PATCH 08/18] fix(rustup): remove standalone components This patch targets the removal of standalone components that are not removed as a part of a toolchain. This was previously ignored. Signed-off-by: innocentzero --- .../pacdef_core/src/backend/actual/rustup.rs | 36 +++++++++++++------ crates/pacdef_core/src/grouping/package.rs | 6 ++++ 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/crates/pacdef_core/src/backend/actual/rustup.rs b/crates/pacdef_core/src/backend/actual/rustup.rs index 2f63ddd..875ce93 100644 --- a/crates/pacdef_core/src/backend/actual/rustup.rs +++ b/crates/pacdef_core/src/backend/actual/rustup.rs @@ -77,8 +77,7 @@ impl Backend for Rustup { let mut iter = p.name.split('/'); let toolchain = iter.next().expect("Toolchain not specified!"); let component = iter.next().expect("Component not specified!"); - cmd.arg(format!("{toolchain}")); - cmd.arg(format!("{component}")); + cmd.arg(format!("{toolchain}")).arg(format!("{component}")); } _ => panic!("No such type is managed by rustup!"), } @@ -97,15 +96,33 @@ impl Backend for Rustup { ) -> anyhow::Result { let mut result: anyhow::Result = Ok(std::process::ExitStatus::from_raw(0)); + let mut toolchains_rem = Vec::new(); + for p in packages { - let repo = p - .repo - .as_ref() - .expect("Not specified whether it is a toolchain or a component!"); + let repo = p.repo("Not specified whether it is a toolchain or a component"); if repo == "toolchain" { let mut cmd = Command::new(self.get_binary()); - cmd.args(self.get_remove_switches(repo)); - cmd.arg(format!("{}", p.name)); + cmd.args(self.get_remove_switches(repo)) + .arg(format!("{}", p.name)); + toolchains_rem.push(p.name.as_str()); + result = cmd.status().context("Removing toolchain {p}"); + if !result.as_ref().is_ok_and(|exit| exit.success()) { + return result; + } + } + } + for p in packages { + let repo = p.repo("Not specified whether it is a toolchain or a component"); + let mut iter = p.name.split('/'); + let toolchain = iter + .next() + .expect("No toolchain name provided for component"); + if repo == "component" && !toolchains_rem.contains(&toolchain) { + let mut cmd = Command::new(self.get_binary()); + cmd.args(self.get_remove_switches(repo)).arg(toolchain).arg( + iter.next() + .expect(format!("Component name not provided for {}", p.name).as_str()), + ); result = cmd.status().context("Removing toolchain {p}"); if !result.as_ref().is_ok_and(|exit| exit.success()) { return result; @@ -155,8 +172,7 @@ impl Rustup { let mut val = Vec::new(); for toolchain in toolchains { let mut cmd = Command::new(self.get_binary()); - cmd.args(args); - cmd.arg(&toolchain); + cmd.args(args).arg(&toolchain); let output = String::from_utf8(cmd.output()?.stdout)?; for i in output.lines() { let mut it = i.splitn(3, "-"); diff --git a/crates/pacdef_core/src/grouping/package.rs b/crates/pacdef_core/src/grouping/package.rs index ed12a76..d5bcea0 100644 --- a/crates/pacdef_core/src/grouping/package.rs +++ b/crates/pacdef_core/src/grouping/package.rs @@ -48,6 +48,12 @@ impl Package { } } + /// Returns the repo name as a reference. + /// Panics if repo name is `None` with a custom error message. + pub(crate) fn repo(&self, msg: &str) -> &str { + self.repo.as_ref().expect(msg) + } + /// Try to parse a string (from a line in a group file) and return a package. /// From the string, any possible comment is removed and whitespace is trimmed. /// Returns `None` if there is nothing left after trimming. From c7596f62b75981f8042d7d67194b3fd75be28186 Mon Sep 17 00:00:00 2001 From: innocentzero Date: Mon, 25 Mar 2024 04:28:06 +0530 Subject: [PATCH 09/18] refact(rustup): Use anyhow::Error Remove repeated instances of anyhow::Error and make the code sparser. Signed-off-by: innocentzero --- .../pacdef_core/src/backend/actual/rustup.rs | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/crates/pacdef_core/src/backend/actual/rustup.rs b/crates/pacdef_core/src/backend/actual/rustup.rs index 875ce93..5140314 100644 --- a/crates/pacdef_core/src/backend/actual/rustup.rs +++ b/crates/pacdef_core/src/backend/actual/rustup.rs @@ -1,11 +1,11 @@ use crate::backend::backend_trait::{Backend, Switches, Text}; use crate::backend::macros::impl_backend_constants; use crate::{Group, Package}; -use anyhow::Context; +use anyhow::{Context, Result}; use core::panic; use std::collections::HashSet; use std::os::unix::process::ExitStatusExt; -use std::process::Command; +use std::process::{Command, ExitStatus}; #[derive(Debug, Clone)] pub struct Rustup { @@ -26,7 +26,7 @@ const SUPPORTS_AS_DEPENDENCY: bool = false; impl Backend for Rustup { impl_backend_constants!(); - fn get_all_installed_packages(&self) -> anyhow::Result> { + fn get_all_installed_packages(&self) -> Result> { let mut toolchains_vec = self .run_toolchain_command(self.get_info_switches("toolchain")) .context("Getting installed toolchains")?; @@ -46,22 +46,16 @@ impl Backend for Rustup { Ok(toolchains) } - fn get_explicitly_installed_packages(&self) -> anyhow::Result> { + fn get_explicitly_installed_packages(&self) -> Result> { self.get_all_installed_packages() .context("Getting all installed packages") } - fn make_dependency(&self, _: &[Package]) -> anyhow::Result { + fn make_dependency(&self, _: &[Package]) -> Result { panic!("Not supported by {}", self.get_binary()) } - fn install_packages( - &self, - packages: &[Package], - _: bool, - ) -> anyhow::Result { - let mut result: anyhow::Result = - Ok(std::process::ExitStatus::from_raw(0)); + fn install_packages(&self, packages: &[Package], _: bool) -> Result { for p in packages { let repo = p .repo @@ -168,7 +162,7 @@ impl Rustup { &self, args: &[&str], toolchains: &mut Vec, - ) -> Result, anyhow::Error> { + ) -> Result> { let mut val = Vec::new(); for toolchain in toolchains { let mut cmd = Command::new(self.get_binary()); @@ -194,7 +188,7 @@ impl Rustup { } Ok(val) } - fn run_toolchain_command(&self, args: &[&str]) -> Result, anyhow::Error> { + fn run_toolchain_command(&self, args: &[&str]) -> Result> { let mut cmd = Command::new(self.get_binary()); cmd.args(args); let output = String::from_utf8(cmd.output()?.stdout)?; From a963d6a2dbdd449aff28761b1f5d045c9d041004 Mon Sep 17 00:00:00 2001 From: innocentzero Date: Mon, 25 Mar 2024 04:31:17 +0530 Subject: [PATCH 10/18] refact(rustup): Remove clippy warnings Clippy warnings were not enabled at the time of the previous commits. Signed-off-by: innocentzero --- .../pacdef_core/src/backend/actual/rustup.rs | 43 +++++++++++-------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/crates/pacdef_core/src/backend/actual/rustup.rs b/crates/pacdef_core/src/backend/actual/rustup.rs index 5140314..6272fab 100644 --- a/crates/pacdef_core/src/backend/actual/rustup.rs +++ b/crates/pacdef_core/src/backend/actual/rustup.rs @@ -28,7 +28,7 @@ impl Backend for Rustup { fn get_all_installed_packages(&self) -> Result> { let mut toolchains_vec = self - .run_toolchain_command(self.get_info_switches("toolchain")) + .run_toolchain_command(get_info_switches("toolchain")) .context("Getting installed toolchains")?; let mut toolchains: HashSet = toolchains_vec @@ -37,12 +37,13 @@ impl Backend for Rustup { .collect(); let packages: HashSet = self - .run_component_command(self.get_info_switches("component"), &mut toolchains_vec) + .run_component_command(get_info_switches("component"), &mut toolchains_vec) .context("Getting installed components")? .iter() .map(|name| ["component", name].join("/").into()) .collect(); - toolchains.extend(packages.into_iter()); + + toolchains.extend(packages); Ok(toolchains) } @@ -61,26 +62,27 @@ impl Backend for Rustup { .repo .as_ref() .expect("Not specified whether it is a toolchain or a component!"); + let mut cmd = Command::new(self.get_binary()); - cmd.args(self.get_install_switches(repo)); + cmd.args(get_install_switches(repo)); match repo.as_str() { "toolchain" => { - cmd.arg(format!("{}", p.name)); + cmd.arg(&p.name); } "component" => { let mut iter = p.name.split('/'); let toolchain = iter.next().expect("Toolchain not specified!"); let component = iter.next().expect("Component not specified!"); - cmd.arg(format!("{toolchain}")).arg(format!("{component}")); + cmd.arg(toolchain).arg(component); } _ => panic!("No such type is managed by rustup!"), } - result = cmd.status().context("Installing toolchain {p}"); + let result = cmd.status().context("Installing toolchain {p}"); if !result.as_ref().is_ok_and(|exit| exit.success()) { return result; } } - result + Ok(ExitStatus::from_raw(0)) } fn remove_packages( @@ -88,42 +90,45 @@ impl Backend for Rustup { packages: &[Package], _: bool, ) -> anyhow::Result { - let mut result: anyhow::Result = - Ok(std::process::ExitStatus::from_raw(0)); let mut toolchains_rem = Vec::new(); for p in packages { - let repo = p.repo("Not specified whether it is a toolchain or a component"); + let repo = p + .repo + .as_ref() + .expect("Not specified whether it is a toolchain or a component"); if repo == "toolchain" { let mut cmd = Command::new(self.get_binary()); - cmd.args(self.get_remove_switches(repo)) - .arg(format!("{}", p.name)); + cmd.args(get_remove_switches(repo)).arg(&p.name); toolchains_rem.push(p.name.as_str()); - result = cmd.status().context("Removing toolchain {p}"); + let result = cmd.status().context("Removing toolchain {p}"); if !result.as_ref().is_ok_and(|exit| exit.success()) { return result; } } } for p in packages { - let repo = p.repo("Not specified whether it is a toolchain or a component"); + let repo = p + .repo + .as_ref() + .expect("Not specified whether it is a toolchain or a component"); let mut iter = p.name.split('/'); let toolchain = iter .next() .expect("No toolchain name provided for component"); if repo == "component" && !toolchains_rem.contains(&toolchain) { let mut cmd = Command::new(self.get_binary()); - cmd.args(self.get_remove_switches(repo)).arg(toolchain).arg( + cmd.args(get_remove_switches(repo)).arg(toolchain).arg( iter.next() - .expect(format!("Component name not provided for {}", p.name).as_str()), + .unwrap_or_else(|| panic!("Component name not provided for {}", p.name)), ); - result = cmd.status().context("Removing toolchain {p}"); + let result = cmd.status().context("Removing toolchain {p}"); if !result.as_ref().is_ok_and(|exit| exit.success()) { return result; } } } - result + Ok(ExitStatus::from_raw(0)) } } From c03baf221f53a4a31f5d4fe1afa9cd9073c71f56 Mon Sep 17 00:00:00 2001 From: innocentzero Date: Mon, 25 Mar 2024 04:33:49 +0530 Subject: [PATCH 11/18] refact(rustup): change methods to functions Remove the methods that don't require access to the backend into separate functions rather than have them as methods. Signed-off-by: innocentzero --- .../pacdef_core/src/backend/actual/rustup.rs | 45 +++++++++---------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/crates/pacdef_core/src/backend/actual/rustup.rs b/crates/pacdef_core/src/backend/actual/rustup.rs index 6272fab..f4230b6 100644 --- a/crates/pacdef_core/src/backend/actual/rustup.rs +++ b/crates/pacdef_core/src/backend/actual/rustup.rs @@ -139,30 +139,6 @@ impl Rustup { } } - fn get_install_switches(&self, repotype: &str) -> Switches { - match repotype { - "toolchain" => &["toolchain", "install"], - "component" => &["component", "add", "--toolchain"], - _ => panic!("No such type managed by rust"), - } - } - - fn get_remove_switches(&self, repotype: &str) -> Switches { - match repotype { - "toolchain" => &["toolchain", "uninstall"], - "component" => &["component", "remove", "--toolchain"], - _ => panic!("No such type managed by rust"), - } - } - - fn get_info_switches(&self, repotype: &str) -> Switches { - match repotype { - "toolchain" => &["toolchain", "list"], - "component" => &["component", "list", "--installed", "--toolchain"], - _ => panic!("No such type managed by rust"), - } - } - fn run_component_command( &self, args: &[&str], @@ -205,3 +181,24 @@ impl Rustup { Ok(val) } } +fn get_install_switches(repotype: &str) -> Switches { + match repotype { + "toolchain" => &["toolchain", "install"], + "component" => &["component", "add", "--toolchain"], + _ => panic!("No such type managed by rust"), + } +} +fn get_remove_switches(repotype: &str) -> Switches { + match repotype { + "toolchain" => &["toolchain", "uninstall"], + "component" => &["component", "remove", "--toolchain"], + _ => panic!("No such type managed by rust"), + } +} +fn get_info_switches(repotype: &str) -> Switches { + match repotype { + "toolchain" => &["toolchain", "list"], + "component" => &["component", "list", "--installed", "--toolchain"], + _ => panic!("No such type managed by rust"), + } +} From ff25f2f55d12a62239b8943b2afb00e73ef721ac Mon Sep 17 00:00:00 2001 From: innocentzero Date: Tue, 26 Mar 2024 23:36:22 +0530 Subject: [PATCH 12/18] refact(rustup): Refactor component installation Signed-off-by: innocentzero --- .../pacdef_core/src/backend/actual/rustup.rs | 43 ++++++++++++------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/crates/pacdef_core/src/backend/actual/rustup.rs b/crates/pacdef_core/src/backend/actual/rustup.rs index f4230b6..d68b8ed 100644 --- a/crates/pacdef_core/src/backend/actual/rustup.rs +++ b/crates/pacdef_core/src/backend/actual/rustup.rs @@ -149,22 +149,8 @@ impl Rustup { let mut cmd = Command::new(self.get_binary()); cmd.args(args).arg(&toolchain); let output = String::from_utf8(cmd.output()?.stdout)?; - for i in output.lines() { - let mut it = i.splitn(3, "-"); - let component = it.next().expect("Component name is empty!"); - match component { - "cargo" | "rustfmt" | "clippy" | "miri" | "rls" | "rustc" => { - val.push([toolchain, component].join("/")); - } - _ => { - let component = [ - component, - it.next().expect("No such component is managed by rustup"), - ] - .join("-"); - val.push([toolchain, component.as_str()].join("/")); - } - } + for line in output.lines() { + install_components(line, toolchain, &mut val); } } Ok(val) @@ -181,6 +167,7 @@ impl Rustup { Ok(val) } } + fn get_install_switches(repotype: &str) -> Switches { match repotype { "toolchain" => &["toolchain", "install"], @@ -188,6 +175,7 @@ fn get_install_switches(repotype: &str) -> Switches { _ => panic!("No such type managed by rust"), } } + fn get_remove_switches(repotype: &str) -> Switches { match repotype { "toolchain" => &["toolchain", "uninstall"], @@ -195,6 +183,7 @@ fn get_remove_switches(repotype: &str) -> Switches { _ => panic!("No such type managed by rust"), } } + fn get_info_switches(repotype: &str) -> Switches { match repotype { "toolchain" => &["toolchain", "list"], @@ -202,3 +191,25 @@ fn get_info_switches(repotype: &str) -> Switches { _ => panic!("No such type managed by rust"), } } + +fn install_components(line: &str, toolchain: &str, val: &mut Vec) { + let mut chunks = line.splitn(3, '-'); + let component = chunks.next().expect("Component name is empty!"); + match component { + // these are the only components that have a single word name + "cargo" | "rustfmt" | "clippy" | "miri" | "rls" | "rustc" => { + val.push([toolchain, component].join("/")); + } + // all the others have two words hyphenated as component names + _ => { + let component = [ + component, + chunks + .next() + .expect("No such component is managed by rustup"), + ] + .join("-"); + val.push([toolchain, component.as_str()].join("/")); + } + } +} From 0c731fa54b8fe8417ef5b8e0d6f8c3571bee64cc Mon Sep 17 00:00:00 2001 From: innocentzero Date: Tue, 26 Mar 2024 23:38:36 +0530 Subject: [PATCH 13/18] refact(rustup): Apply clippy suggestions Signed-off-by: innocentzero --- crates/pacdef_core/src/backend/actual/rustup.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/pacdef_core/src/backend/actual/rustup.rs b/crates/pacdef_core/src/backend/actual/rustup.rs index d68b8ed..fa0e1ed 100644 --- a/crates/pacdef_core/src/backend/actual/rustup.rs +++ b/crates/pacdef_core/src/backend/actual/rustup.rs @@ -149,8 +149,8 @@ impl Rustup { let mut cmd = Command::new(self.get_binary()); cmd.args(args).arg(&toolchain); let output = String::from_utf8(cmd.output()?.stdout)?; - for line in output.lines() { - install_components(line, toolchain, &mut val); + for component in output.lines() { + install_components(component, toolchain, &mut val); } } Ok(val) @@ -161,7 +161,7 @@ impl Rustup { let output = String::from_utf8(cmd.output()?.stdout)?; let mut val = Vec::new(); for i in output.lines() { - let mut it = i.splitn(2, "-"); + let mut it = i.splitn(2, '-'); val.push(it.next().expect("Toolchain name is empty.").to_string()); } Ok(val) From fc83c43997708822f77127aef7ca2a19ded774e5 Mon Sep 17 00:00:00 2001 From: innocentzero Date: Tue, 26 Mar 2024 23:39:09 +0530 Subject: [PATCH 14/18] refact(packaging): remove unused function Signed-off-by: innocentzero --- crates/pacdef_core/src/grouping/package.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/crates/pacdef_core/src/grouping/package.rs b/crates/pacdef_core/src/grouping/package.rs index d5bcea0..ed12a76 100644 --- a/crates/pacdef_core/src/grouping/package.rs +++ b/crates/pacdef_core/src/grouping/package.rs @@ -48,12 +48,6 @@ impl Package { } } - /// Returns the repo name as a reference. - /// Panics if repo name is `None` with a custom error message. - pub(crate) fn repo(&self, msg: &str) -> &str { - self.repo.as_ref().expect(msg) - } - /// Try to parse a string (from a line in a group file) and return a package. /// From the string, any possible comment is removed and whitespace is trimmed. /// Returns `None` if there is nothing left after trimming. From 6f92e6677721492a125dbc9acc5ef1fdd7fffe51 Mon Sep 17 00:00:00 2001 From: innocentzero Date: Fri, 29 Mar 2024 22:22:27 +0530 Subject: [PATCH 15/18] refact(rustup): Use RepoType instead of strings Use RepoType enums instead of strings to match in various places. Signed-off-by: innocentzero --- .../pacdef_core/src/backend/actual/rustup.rs | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/crates/pacdef_core/src/backend/actual/rustup.rs b/crates/pacdef_core/src/backend/actual/rustup.rs index fa0e1ed..77778f4 100644 --- a/crates/pacdef_core/src/backend/actual/rustup.rs +++ b/crates/pacdef_core/src/backend/actual/rustup.rs @@ -12,6 +12,11 @@ pub struct Rustup { pub(crate) packages: HashSet, } +enum Repotype { + Toolchain, + Component, +} + const BINARY: Text = "rustup"; const SECTION: Text = "rustup"; @@ -28,7 +33,7 @@ impl Backend for Rustup { fn get_all_installed_packages(&self) -> Result> { let mut toolchains_vec = self - .run_toolchain_command(get_info_switches("toolchain")) + .run_toolchain_command(get_info_switches(Repotype::Toolchain)) .context("Getting installed toolchains")?; let mut toolchains: HashSet = toolchains_vec @@ -37,7 +42,7 @@ impl Backend for Rustup { .collect(); let packages: HashSet = self - .run_component_command(get_info_switches("component"), &mut toolchains_vec) + .run_component_command(get_info_switches(Repotype::Component), &mut toolchains_vec) .context("Getting installed components")? .iter() .map(|name| ["component", name].join("/").into()) @@ -64,12 +69,13 @@ impl Backend for Rustup { .expect("Not specified whether it is a toolchain or a component!"); let mut cmd = Command::new(self.get_binary()); - cmd.args(get_install_switches(repo)); match repo.as_str() { "toolchain" => { + cmd.args(get_install_switches(Repotype::Toolchain)); cmd.arg(&p.name); } "component" => { + cmd.args(get_install_switches(Repotype::Component)); let mut iter = p.name.split('/'); let toolchain = iter.next().expect("Toolchain not specified!"); let component = iter.next().expect("Component not specified!"); @@ -99,7 +105,8 @@ impl Backend for Rustup { .expect("Not specified whether it is a toolchain or a component"); if repo == "toolchain" { let mut cmd = Command::new(self.get_binary()); - cmd.args(get_remove_switches(repo)).arg(&p.name); + cmd.args(get_remove_switches(Repotype::Toolchain)) + .arg(&p.name); toolchains_rem.push(p.name.as_str()); let result = cmd.status().context("Removing toolchain {p}"); if !result.as_ref().is_ok_and(|exit| exit.success()) { @@ -168,27 +175,24 @@ impl Rustup { } } -fn get_install_switches(repotype: &str) -> Switches { +fn get_install_switches(repotype: Repotype) -> Switches { match repotype { - "toolchain" => &["toolchain", "install"], - "component" => &["component", "add", "--toolchain"], - _ => panic!("No such type managed by rust"), + Repotype::Toolchain => &["toolchain", "install"], + Repotype::Component => &["component", "add", "--toolchain"], } } -fn get_remove_switches(repotype: &str) -> Switches { +fn get_remove_switches(repotype: Repotype) -> Switches { match repotype { - "toolchain" => &["toolchain", "uninstall"], - "component" => &["component", "remove", "--toolchain"], - _ => panic!("No such type managed by rust"), + Repotype::Toolchain => &["toolchain", "uninstall"], + Repotype::Component => &["component", "remove", "--toolchain"], } } -fn get_info_switches(repotype: &str) -> Switches { +fn get_info_switches(repotype: Repotype) -> Switches { match repotype { - "toolchain" => &["toolchain", "list"], - "component" => &["component", "list", "--installed", "--toolchain"], - _ => panic!("No such type managed by rust"), + Repotype::Toolchain => &["toolchain", "list"], + Repotype::Component => &["component", "list", "--installed", "--toolchain"], } } From fd476599599ebbfee7246ef9ef8456678e4023ce Mon Sep 17 00:00:00 2001 From: innocentzero Date: Fri, 29 Mar 2024 22:23:57 +0530 Subject: [PATCH 16/18] refact(rustup): Use bail instead of panic Use anyhow::bail to return an Err type instead of panicking and exiting the program. Signed-off-by: innocentzero --- .../pacdef_core/src/backend/actual/rustup.rs | 70 +++++++++++-------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/crates/pacdef_core/src/backend/actual/rustup.rs b/crates/pacdef_core/src/backend/actual/rustup.rs index 77778f4..877aae0 100644 --- a/crates/pacdef_core/src/backend/actual/rustup.rs +++ b/crates/pacdef_core/src/backend/actual/rustup.rs @@ -57,16 +57,17 @@ impl Backend for Rustup { .context("Getting all installed packages") } - fn make_dependency(&self, _: &[Package]) -> Result { - panic!("Not supported by {}", self.get_binary()) + fn make_dependency(&self, _: &[Package]) -> Result { + anyhow::bail!("Not supported by {}", self.get_binary()) } - fn install_packages(&self, packages: &[Package], _: bool) -> Result { + fn install_packages(&self, packages: &[Package], _: bool) -> Result { for p in packages { - let repo = p - .repo - .as_ref() - .expect("Not specified whether it is a toolchain or a component!"); + let repo = if p.repo.is_some() { + p.repo.as_ref().expect("This should never be reached") + } else { + anyhow::bail!("Not specified whether it is a toolchain or a component") + }; let mut cmd = Command::new(self.get_binary()); match repo.as_str() { @@ -81,8 +82,9 @@ impl Backend for Rustup { let component = iter.next().expect("Component not specified!"); cmd.arg(toolchain).arg(component); } - _ => panic!("No such type is managed by rustup!"), + _ => anyhow::bail!("No such type is managed by rustup!"), } + let result = cmd.status().context("Installing toolchain {p}"); if !result.as_ref().is_ok_and(|exit| exit.success()) { return result; @@ -91,44 +93,54 @@ impl Backend for Rustup { Ok(ExitStatus::from_raw(0)) } - fn remove_packages( - &self, - packages: &[Package], - _: bool, - ) -> anyhow::Result { + fn remove_packages(&self, packages: &[Package], _: bool) -> Result { let mut toolchains_rem = Vec::new(); for p in packages { - let repo = p - .repo - .as_ref() - .expect("Not specified whether it is a toolchain or a component"); + let repo = if p.repo.is_some() { + p.repo.as_ref().expect("This will never be printed!") + } else { + anyhow::bail!("Not specified whether it is a toolchain or a component") + }; + if repo == "toolchain" { let mut cmd = Command::new(self.get_binary()); cmd.args(get_remove_switches(Repotype::Toolchain)) .arg(&p.name); toolchains_rem.push(p.name.as_str()); + let result = cmd.status().context("Removing toolchain {p}"); if !result.as_ref().is_ok_and(|exit| exit.success()) { return result; } } } + for p in packages { - let repo = p - .repo - .as_ref() - .expect("Not specified whether it is a toolchain or a component"); - let mut iter = p.name.split('/'); - let toolchain = iter - .next() - .expect("No toolchain name provided for component"); + let repo = if p.repo.is_some() { + p.repo.as_ref().expect("This will never be printed!") + } else { + anyhow::bail!("Not specified whether it is a toolchain or a component") + }; + + let mut iter = p.name.split('/').peekable(); + let toolchain = if iter.peek().is_some() { + iter.next().expect("This should never be printed") + } else { + anyhow::bail!("No toolchain name provided for the given component!") + }; + if repo == "component" && !toolchains_rem.contains(&toolchain) { let mut cmd = Command::new(self.get_binary()); - cmd.args(get_remove_switches(repo)).arg(toolchain).arg( - iter.next() - .unwrap_or_else(|| panic!("Component name not provided for {}", p.name)), - ); + + cmd.args(get_remove_switches(Repotype::Component)) + .arg(toolchain) + .arg( + iter.next().unwrap_or_else(|| { + panic!("Component name not provided for {}", p.name) + }), + ); + let result = cmd.status().context("Removing toolchain {p}"); if !result.as_ref().is_ok_and(|exit| exit.success()) { return result; From 75709a7ed9bb7ed95f82c2e885f5d1f66c60adb5 Mon Sep 17 00:00:00 2001 From: innocentzero Date: Tue, 2 Apr 2024 04:58:19 +0530 Subject: [PATCH 17/18] refact(rustup): Use match statements and bail Use match statements for Option types and use bail! macro to utilize recoverable errors. Signed-off-by: innocentzero --- .../pacdef_core/src/backend/actual/rustup.rs | 76 +++++++++++-------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/crates/pacdef_core/src/backend/actual/rustup.rs b/crates/pacdef_core/src/backend/actual/rustup.rs index 877aae0..1e26547 100644 --- a/crates/pacdef_core/src/backend/actual/rustup.rs +++ b/crates/pacdef_core/src/backend/actual/rustup.rs @@ -1,8 +1,7 @@ use crate::backend::backend_trait::{Backend, Switches, Text}; use crate::backend::macros::impl_backend_constants; use crate::{Group, Package}; -use anyhow::{Context, Result}; -use core::panic; +use anyhow::{bail, Context, Result}; use std::collections::HashSet; use std::os::unix::process::ExitStatusExt; use std::process::{Command, ExitStatus}; @@ -58,15 +57,14 @@ impl Backend for Rustup { } fn make_dependency(&self, _: &[Package]) -> Result { - anyhow::bail!("Not supported by {}", self.get_binary()) + bail!("Not supported by {}", self.get_binary()) } fn install_packages(&self, packages: &[Package], _: bool) -> Result { for p in packages { - let repo = if p.repo.is_some() { - p.repo.as_ref().expect("This should never be reached") - } else { - anyhow::bail!("Not specified whether it is a toolchain or a component") + let repo = match p.repo.as_ref() { + Some(name) => name, + None => bail!("Not specified whether it is a toolchain or a component"), }; let mut cmd = Command::new(self.get_binary()); @@ -77,12 +75,22 @@ impl Backend for Rustup { } "component" => { cmd.args(get_install_switches(Repotype::Component)); + let mut iter = p.name.split('/'); - let toolchain = iter.next().expect("Toolchain not specified!"); - let component = iter.next().expect("Component not specified!"); - cmd.arg(toolchain).arg(component); + + let toolchain = match iter.next() { + Some(name) => name, + None => bail!("Toolchain not specified!"), + }; + cmd.arg(toolchain); + + let component = match iter.next() { + Some(name) => name, + None => bail!("Component not specified!"), + }; + cmd.arg(component); } - _ => anyhow::bail!("No such type is managed by rustup!"), + _ => bail!("No such type is managed by rustup!"), } let result = cmd.status().context("Installing toolchain {p}"); @@ -97,10 +105,9 @@ impl Backend for Rustup { let mut toolchains_rem = Vec::new(); for p in packages { - let repo = if p.repo.is_some() { - p.repo.as_ref().expect("This will never be printed!") - } else { - anyhow::bail!("Not specified whether it is a toolchain or a component") + let repo = match p.repo.as_ref() { + Some(reponame) => reponame, + None => bail!("Not specified whether it is a toolchain or a component"), }; if repo == "toolchain" { @@ -117,29 +124,29 @@ impl Backend for Rustup { } for p in packages { - let repo = if p.repo.is_some() { - p.repo.as_ref().expect("This will never be printed!") - } else { - anyhow::bail!("Not specified whether it is a toolchain or a component") + let repo = match p.repo.as_ref() { + Some(reponame) => reponame, + None => bail!("Not specified whether it is a toolchain or a component"), }; let mut iter = p.name.split('/').peekable(); - let toolchain = if iter.peek().is_some() { - iter.next().expect("This should never be printed") - } else { - anyhow::bail!("No toolchain name provided for the given component!") + let toolchain = match iter.peek() { + Some(name) => name, + None => bail!("No toolchain name provided for the given component!"), }; - if repo == "component" && !toolchains_rem.contains(&toolchain) { + if repo == "component" && !toolchains_rem.contains(toolchain) { let mut cmd = Command::new(self.get_binary()); cmd.args(get_remove_switches(Repotype::Component)) - .arg(toolchain) - .arg( - iter.next().unwrap_or_else(|| { - panic!("Component name not provided for {}", p.name) - }), - ); + .arg(toolchain); + + let component = match iter.next() { + Some(name) => name, + None => bail!("No component name provided for {}", p.name), + }; + + cmd.arg(component); let result = cmd.status().context("Removing toolchain {p}"); if !result.as_ref().is_ok_and(|exit| exit.success()) { @@ -179,9 +186,12 @@ impl Rustup { cmd.args(args); let output = String::from_utf8(cmd.output()?.stdout)?; let mut val = Vec::new(); - for i in output.lines() { - let mut it = i.splitn(2, '-'); - val.push(it.next().expect("Toolchain name is empty.").to_string()); + for line in output.lines() { + let toolchain = line.split('-').next(); + match toolchain { + Some(name) => val.push(name.to_string()), + None => bail!("Toolchain name not provided!"), + } } Ok(val) } From a5a0765928ad91ad15b8a84d452e1883580029e9 Mon Sep 17 00:00:00 2001 From: innocentzero Date: Tue, 2 Apr 2024 17:36:00 +0530 Subject: [PATCH 18/18] fix(rustup): Fix individual component uninstall Signed-off-by: innocentzero --- crates/pacdef_core/src/backend/actual/rustup.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/pacdef_core/src/backend/actual/rustup.rs b/crates/pacdef_core/src/backend/actual/rustup.rs index 1e26547..a9f6db4 100644 --- a/crates/pacdef_core/src/backend/actual/rustup.rs +++ b/crates/pacdef_core/src/backend/actual/rustup.rs @@ -140,7 +140,7 @@ impl Backend for Rustup { cmd.args(get_remove_switches(Repotype::Component)) .arg(toolchain); - + iter.next(); let component = match iter.next() { Some(name) => name, None => bail!("No component name provided for {}", p.name),