TRUC
This commit is contained in:
parent
7d9e3d63b7
commit
89ef66a694
19 changed files with 461 additions and 64 deletions
|
|
@ -1,6 +1,8 @@
|
|||
use rayon::prelude::*;
|
||||
|
||||
use crate::utils::cmd::{Cmd, CmdOutput};
|
||||
|
||||
use super::{PackageError, PackageList, PackageManager};
|
||||
use super::{PackageError, PackageList, PackageManager, IntoPackageList};
|
||||
|
||||
/// This structure is mostly used as an indirection for testing purposes.
|
||||
/// But you can use it to build your own apt commands.
|
||||
|
|
@ -40,6 +42,14 @@ impl AptCmd {
|
|||
#[derive(Debug)]
|
||||
pub struct AptManager;
|
||||
|
||||
impl AptManager {
|
||||
fn is_installed_list(&self, list: &PackageList) -> Result<bool, PackageError> {
|
||||
let res = Cmd::new("dpkg").arg("-s").args(list.list()).run()?;
|
||||
|
||||
Ok(res.success)
|
||||
}
|
||||
}
|
||||
|
||||
impl PackageManager for AptManager {
|
||||
fn name(&self) -> &'static str {
|
||||
"apt"
|
||||
|
|
@ -54,7 +64,26 @@ impl PackageManager for AptManager {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn is_installed(&self, pkg: &str) -> Result<bool, PackageError> {
|
||||
let res = Cmd::new("dpkg").arg("-s").arg(pkg).run()?;
|
||||
|
||||
Ok(res.success)
|
||||
}
|
||||
|
||||
fn install(&self, list: PackageList) -> Result<(), PackageError> {
|
||||
// Filter out already installed packages
|
||||
// let list: Vec<String> = list.list().par_iter().filter_map(|pkg| {
|
||||
// if ! self.is_installed(&pkg).unwrap() {
|
||||
// Some(pkg.to_string())
|
||||
// } else {
|
||||
// None
|
||||
// }
|
||||
// }).collect();
|
||||
if self.is_installed_list(&list)? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
//let res = AptCmd::install(list.into_package_list()).run()?;
|
||||
let res = AptCmd::install(list).run()?;
|
||||
|
||||
if ! res.success {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
use serde::Serialize;
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
|
||||
use crate::utils::serde::string_or_seq_string;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct PackageList {
|
||||
#[serde(deserialize_with = "string_or_seq_string")]
|
||||
pub list: Vec<String>,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use serde::Serialize;
|
||||
use serde::{Serialize, Deserialize, Deserializer};
|
||||
|
||||
use crate::{Module, ModuleSetup};
|
||||
use crate::facts::{Facts, os::OsFamily};
|
||||
|
|
@ -19,12 +19,25 @@ pub use builder::{PackageArgsBuilder, NoManager};
|
|||
|
||||
pub type PackageStatus = ();
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct PackageArgs {
|
||||
name: PackageList,
|
||||
state: PackageState,
|
||||
}
|
||||
|
||||
impl ModuleSetup<PackageModule<Box<dyn PackageManager>>, PackageArgs, (), PackageError> for PackageArgs {
|
||||
fn with_facts(self, facts: &Facts) -> PackageModule<Box<dyn PackageManager>> {
|
||||
let manager: Box<dyn PackageManager> = match facts.os.family() {
|
||||
OsFamily::Debian => Box::new(AptManager),
|
||||
OsFamily::Archlinux => Box::new(PacmanManager),
|
||||
};
|
||||
|
||||
PackageModule {
|
||||
args: self,
|
||||
manager,
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
|
||||
pub enum PackageState {
|
||||
Present,
|
||||
|
|
@ -32,6 +45,21 @@ pub enum PackageState {
|
|||
Latest,
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for PackageState {
|
||||
fn deserialize<D>(de: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let variant = String::deserialize(de)?;
|
||||
Ok(match variant.as_str() {
|
||||
"present" => PackageState::Present,
|
||||
"absent" => PackageState::Absent,
|
||||
"latest" => PackageState::Latest,
|
||||
_other => unimplemented!(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct PackageModule<Manager> {
|
||||
manager: Manager,
|
||||
|
|
@ -78,6 +106,12 @@ impl ModuleSetup<PackageModule<Box<dyn PackageManager>>, PackageArgs, (), Packag
|
|||
}
|
||||
}
|
||||
|
||||
// Stupid impl just for tests
|
||||
impl ModuleSetup<PackageModule<Box<dyn PackageManager>>, PackageArgs, (), PackageError> for PackageModule<Box<dyn PackageManager>> {
|
||||
fn with_facts(self, _facts: &Facts) -> PackageModule<Box<dyn PackageManager>> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl PackageModule<NoManager> {
|
||||
pub fn new() -> PackageArgsBuilder<builder::NoPackage, builder::NoState, builder::NoManager> {
|
||||
|
|
@ -100,6 +134,7 @@ impl From<std::io::Error> for PackageError {
|
|||
pub trait PackageManager: std::fmt::Debug {
|
||||
fn name(&self) -> &'static str;
|
||||
fn update(&self) -> Result<(), PackageError>;
|
||||
fn is_installed(&self, pkg: &str) -> Result<bool, PackageError>;
|
||||
fn install(&self, list: PackageList) -> Result<(), PackageError>;
|
||||
fn remove(&self, list: PackageList) -> Result<(), PackageError>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,12 @@ impl PacmanCmd {
|
|||
cmd
|
||||
}
|
||||
|
||||
pub fn is_installed(pkg: &str) -> PacmanCmd {
|
||||
let mut cmd = Self::new();
|
||||
cmd.0 = cmd.0.arg("-Qi").arg(pkg);
|
||||
cmd
|
||||
}
|
||||
|
||||
pub fn install(list: PackageList) -> PacmanCmd {
|
||||
let mut cmd = Self::new();
|
||||
cmd.0 = cmd.0.arg("-S").args(list.list());
|
||||
|
|
@ -56,6 +62,12 @@ impl PackageManager for PacmanManager {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn is_installed(&self, pkg: &str) -> Result<bool, PackageError> {
|
||||
let res = PacmanCmd::is_installed(pkg).run()?;
|
||||
|
||||
Ok(res.success)
|
||||
}
|
||||
|
||||
fn install(&self, list: PackageList) -> Result<(), PackageError> {
|
||||
let res = PacmanCmd::install(list).run()?;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue