From 1b99a4a1ed7772c9b68e59f46e493ea5b4715239 Mon Sep 17 00:00:00 2001 From: fxqnlr Date: Sat, 14 Sep 2024 14:20:52 +0200 Subject: add portage package manager --- src/packages.rs | 18 ++++------------ src/packages/portage.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 56 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/packages.rs b/src/packages.rs index 2eadcfc..de818f4 100644 --- a/src/packages.rs +++ b/src/packages.rs @@ -6,9 +6,7 @@ use serde::{Deserialize, Serialize}; use crate::error::{Error, Result}; -#[cfg(feature = "pacman")] mod pacman; -#[cfg(feature = "portage")] mod portage; #[derive(Debug, Serialize, Deserialize)] @@ -19,7 +17,9 @@ pub struct PackageList { impl PackageList { pub fn install(&self) -> Result<()> { - self.manager.to_package_manager().install(self.packages.clone()) + self.manager + .to_package_manager() + .install(self.packages.clone()) } } @@ -32,19 +32,14 @@ pub struct Package { #[derive(Debug, Clone, clap::ValueEnum, Serialize, Deserialize)] pub enum Manager { - #[cfg(feature = "pacman")] Pacman, - #[cfg(feature = "portage")] Portage, } - impl Manager { pub fn get_manager(manager: Option) -> Result> { #[cfg(not(target_os = "linux"))] - { - return Err(Error::Unsupported); - } + return Err(Error::Unsupported); #[cfg(target_os = "linux")] { @@ -70,9 +65,7 @@ impl Manager { fn from_str(value: &str) -> Result> { Ok(match value { - #[cfg(feature = "pacman")] "arch" => Box::new(Pacman), - #[cfg(feature = "portage")] "gentoo" => Box::new(Portage), _ => return Err(Error::Unsupported), }) @@ -80,15 +73,12 @@ impl Manager { fn to_package_manager(&self) -> Box { match self { - #[cfg(feature = "pacman")] Self::Pacman => Box::new(Pacman), - #[cfg(feature = "portage")] Self::Portage => Box::new(Portage), } } } - pub trait PackageManager { fn get_installed(&self) -> Result; diff --git a/src/packages/portage.rs b/src/packages/portage.rs index 7fa09a8..dac0c2f 100644 --- a/src/packages/portage.rs +++ b/src/packages/portage.rs @@ -1,16 +1,63 @@ -use tracing::error; +use std::process::{Command, Stdio}; -use super::{PackageList, PackageManager}; +use crate::error::Error; + +use super::{Package, PackageList, PackageManager}; pub struct Portage; impl PackageManager for Portage { fn get_installed(&self) -> crate::error::Result { - todo!() + let eix_pkgs = Command::new("eix") + .args(["--world", "-c*"]) + .output() + .unwrap(); + + let eix_pkgs_out = String::from_utf8(eix_pkgs.stdout).unwrap(); + + let mut pkgs: Vec = Vec::new(); + let portage_pkgs: Vec<&str> = eix_pkgs_out.split('\n').collect(); + for pkg in portage_pkgs { + if pkg.is_empty() { + continue; + }; + let split = pkg.split_once('@'); + let info = if let Some(sp) = split { + sp.0 + } else { + return Err(Error::UnknownOutput); + }; + + let (id, version) = if let Some(res) = info.split_once('(') { + (res.0.split_at(4).1.trim().to_string(), res.1.to_string()) + } else { + return Err(Error::UnknownOutput); + }; + + pkgs.push(Package { + id, + version, + explicit: true, + }); + } + + Ok(PackageList { + packages: pkgs, + manager: super::Manager::Portage, + }) } fn install(&self, pkgs: Vec) -> crate::error::Result<()> { - error!("Install {pkgs:?}"); - todo!() + let mut args = vec!["emerge".to_string()]; + + for pkg in pkgs { + args.push(pkg.id); + } + Command::new("doas") + .stdout(Stdio::inherit()) + .args(args) + .spawn()? + .wait_with_output()?; + Ok(()) } } -- cgit v1.2.3