diff options
Diffstat (limited to 'src/packages.rs')
-rw-r--r-- | src/packages.rs | 85 |
1 files changed, 81 insertions, 4 deletions
diff --git a/src/packages.rs b/src/packages.rs index 5ee5664..2eadcfc 100644 --- a/src/packages.rs +++ b/src/packages.rs | |||
@@ -1,19 +1,96 @@ | |||
1 | use std::{fs::File, io::Read}; | ||
2 | |||
3 | use pacman::Pacman; | ||
4 | use portage::Portage; | ||
1 | use serde::{Deserialize, Serialize}; | 5 | use serde::{Deserialize, Serialize}; |
2 | 6 | ||
3 | use crate::error::Result; | 7 | use crate::error::{Error, Result}; |
4 | 8 | ||
5 | pub mod pacman; | 9 | #[cfg(feature = "pacman")] |
6 | pub mod portage; | 10 | mod pacman; |
11 | #[cfg(feature = "portage")] | ||
12 | mod portage; | ||
7 | 13 | ||
8 | #[derive(Debug, Serialize, Deserialize)] | 14 | #[derive(Debug, Serialize, Deserialize)] |
15 | pub struct PackageList { | ||
16 | packages: Vec<Package>, | ||
17 | manager: Manager, | ||
18 | } | ||
19 | |||
20 | impl PackageList { | ||
21 | pub fn install(&self) -> Result<()> { | ||
22 | self.manager.to_package_manager().install(self.packages.clone()) | ||
23 | } | ||
24 | } | ||
25 | |||
26 | #[derive(Debug, Clone, Serialize, Deserialize)] | ||
9 | pub struct Package { | 27 | pub struct Package { |
10 | pub id: String, | 28 | pub id: String, |
11 | pub version: String, | 29 | pub version: String, |
12 | pub explicit: bool, | 30 | pub explicit: bool, |
13 | } | 31 | } |
14 | 32 | ||
33 | #[derive(Debug, Clone, clap::ValueEnum, Serialize, Deserialize)] | ||
34 | pub enum Manager { | ||
35 | #[cfg(feature = "pacman")] | ||
36 | Pacman, | ||
37 | #[cfg(feature = "portage")] | ||
38 | Portage, | ||
39 | } | ||
40 | |||
41 | |||
42 | impl Manager { | ||
43 | pub fn get_manager(manager: Option<Manager>) -> Result<Box<dyn PackageManager>> { | ||
44 | #[cfg(not(target_os = "linux"))] | ||
45 | { | ||
46 | return Err(Error::Unsupported); | ||
47 | } | ||
48 | |||
49 | #[cfg(target_os = "linux")] | ||
50 | { | ||
51 | if let Some(man) = manager { | ||
52 | return Ok(man.to_package_manager()); | ||
53 | } | ||
54 | let mut os_release = File::open("/etc/os-release")?; | ||
55 | let mut content = String::new(); | ||
56 | os_release.read_to_string(&mut content)?; | ||
57 | |||
58 | let lines: Vec<&str> = content.split('\n').collect(); | ||
59 | for line in lines { | ||
60 | let Some((key, value)) = line.split_once('=') else { | ||
61 | continue; | ||
62 | }; | ||
63 | if key == "ID" { | ||
64 | return Self::from_str(value); | ||
65 | } | ||
66 | } | ||
67 | Err(Error::Unsupported) | ||
68 | } | ||
69 | } | ||
70 | |||
71 | fn from_str(value: &str) -> Result<Box<dyn PackageManager>> { | ||
72 | Ok(match value { | ||
73 | #[cfg(feature = "pacman")] | ||
74 | "arch" => Box::new(Pacman), | ||
75 | #[cfg(feature = "portage")] | ||
76 | "gentoo" => Box::new(Portage), | ||
77 | _ => return Err(Error::Unsupported), | ||
78 | }) | ||
79 | } | ||
80 | |||
81 | fn to_package_manager(&self) -> Box<dyn PackageManager> { | ||
82 | match self { | ||
83 | #[cfg(feature = "pacman")] | ||
84 | Self::Pacman => Box::new(Pacman), | ||
85 | #[cfg(feature = "portage")] | ||
86 | Self::Portage => Box::new(Portage), | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | |||
91 | |||
15 | pub trait PackageManager { | 92 | pub trait PackageManager { |
16 | fn get_installed(&self) -> Result<Vec<Package>>; | 93 | fn get_installed(&self) -> Result<PackageList>; |
17 | 94 | ||
18 | fn install(&self, pkgs: Vec<Package>) -> Result<()>; | 95 | fn install(&self, pkgs: Vec<Package>) -> Result<()>; |
19 | } | 96 | } |