summaryrefslogblamecommitdiff
path: root/src/packages.rs
blob: 3ff997d2b3d3135a276b9c2936d112ffc8f85d7f (plain) (tree)
1
2
3
4
5
6
7
8
9

                              
             
             

                     

                                    
                                  
 
        
        
           
            

                                        






                                         


                                           



                                               


                        
                       

 

                                                                
        
        
           


            
              
                                       
                                        
                                       


                                   
















                                                                    
                                              
                        
                                                          


                                      



                                                
                                                                 
                    
                                       
                                       
                                             




                                               
                          
                                                   
 
                                                        
 
use std::{fs::File, io::Read};

use apt::Apt;
use dnf::Dnf;
use pacman::Pacman;
use portage::Portage;
use serde::{Deserialize, Serialize};

use crate::error::{Error, Result};

mod apt;
mod dnf;
mod pacman;
mod portage;

#[derive(Debug, Serialize, Deserialize)]
pub struct PackageList {
    packages: Vec<Package>,
    manager: Manager,
}

impl PackageList {
    pub fn install(&self) -> Result<()> {
        self.manager
            .to_package_manager()
            .install(self.packages.clone())
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Package {
    pub id: String,
    pub version: String,
    pub explicit: bool,
}

#[derive(Debug, Clone, clap::ValueEnum, Serialize, Deserialize)]
pub enum Manager {
    Apt,
    Dnf,
    Pacman,
    Portage,
}

impl Manager {
    pub fn from_sys() -> Result<Self> {
        #[cfg(not(target_os = "linux"))]
        return Err(Error::Unsupported);

        #[cfg(target_os = "linux")]
        {
            let mut os_release = File::open("/etc/os-release")?;
            let mut content = String::new();
            os_release.read_to_string(&mut content)?;

            let lines: Vec<&str> = content.split('\n').collect();
            for line in lines {
                let Some((key, value)) = line.split_once('=') else {
                    continue;
                };
                if key == "ID" {
                    return Self::from_str(value);
                }
            }
            Err(Error::Unsupported)
        }
    }

    fn from_str(value: &str) -> Result<Self> {
        Ok(match value {
            "debian" | "ubuntu" |"linuxmint" => Self::Apt,
            "fedora" => Self::Dnf,
            "arch" => Self::Pacman,
            "gentoo" => Self::Portage,
            _ => return Err(Error::Unsupported),
        })
    }

    pub fn to_package_manager(&self) -> Box<dyn PackageManager> {
        match self {
            Self::Apt => Box::new(Apt),
            Self::Dnf => Box::new(Dnf),
            Self::Pacman => Box::new(Pacman),
            Self::Portage => Box::new(Portage),
        }
    }
}

pub trait PackageManager {
    fn get_installed(&self) -> Result<PackageList>;

    fn install(&self, pkgs: Vec<Package>) -> Result<()>;
}