summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/packages.rs9
-rw-r--r--src/packages/dnf.rs62
-rw-r--r--src/pathinfo.rs23
3 files changed, 85 insertions, 9 deletions
diff --git a/src/packages.rs b/src/packages.rs
index 41b9478..5fb08d0 100644
--- a/src/packages.rs
+++ b/src/packages.rs
@@ -1,11 +1,13 @@
1use std::{fs::File, io::Read}; 1use std::{fs::File, io::Read};
2 2
3use dnf::Dnf;
3use pacman::Pacman; 4use pacman::Pacman;
4use portage::Portage; 5use portage::Portage;
5use serde::{Deserialize, Serialize}; 6use serde::{Deserialize, Serialize};
6 7
7use crate::error::{Error, Result}; 8use crate::error::{Error, Result};
8 9
10mod dnf;
9mod pacman; 11mod pacman;
10mod portage; 12mod portage;
11 13
@@ -32,6 +34,7 @@ pub struct Package {
32 34
33#[derive(Debug, Clone, clap::ValueEnum, Serialize, Deserialize)] 35#[derive(Debug, Clone, clap::ValueEnum, Serialize, Deserialize)]
34pub enum Manager { 36pub enum Manager {
37 Dnf,
35 Pacman, 38 Pacman,
36 Portage, 39 Portage,
37} 40}
@@ -62,14 +65,16 @@ impl Manager {
62 65
63 fn from_str(value: &str) -> Result<Self> { 66 fn from_str(value: &str) -> Result<Self> {
64 Ok(match value { 67 Ok(match value {
65 "arch" => Self::Pacman, 68 "fedora" => Box::new(Dnf),
66 "gentoo" => Self::Portage, 69 "arch" => Box::new(Pacman),
70 "gentoo" => Box::new(Portage),
67 _ => return Err(Error::Unsupported), 71 _ => return Err(Error::Unsupported),
68 }) 72 })
69 } 73 }
70 74
71 pub fn to_package_manager(&self) -> Box<dyn PackageManager> { 75 pub fn to_package_manager(&self) -> Box<dyn PackageManager> {
72 match self { 76 match self {
77 Self::Dnf => Box::new(Dnf),
73 Self::Pacman => Box::new(Pacman), 78 Self::Pacman => Box::new(Pacman),
74 Self::Portage => Box::new(Portage), 79 Self::Portage => Box::new(Portage),
75 } 80 }
diff --git a/src/packages/dnf.rs b/src/packages/dnf.rs
new file mode 100644
index 0000000..6f451ee
--- /dev/null
+++ b/src/packages/dnf.rs
@@ -0,0 +1,62 @@
1use std::process::{Command, Stdio};
2
3use super::{Package, PackageList, PackageManager};
4
5use crate::error::{Error, Result};
6
7pub struct Dnf;
8
9impl PackageManager for Dnf {
10 fn get_installed(&self) -> Result<PackageList> {
11 let list = Command::new("dnf").args(["list", "installed"]).output().unwrap();
12 let explicit_list = Command::new("dnf").args(["repoquery", "--userinstalled"]).output().unwrap();
13
14 let list_str = String::from_utf8(list.stdout).unwrap();
15 let ex_list_str = String::from_utf8(explicit_list.stdout).unwrap();
16
17
18 let mut pkgs: Vec<Package> = Vec::new();
19 let list_lines: Vec<&str> = list_str.split('\n').collect();
20 // Pop first info line
21 let list_lines = &list_lines[1..list_lines.len()];
22 for pkg in list_lines {
23 if pkg.is_empty() {
24 continue;
25 };
26 let split: Vec<&str> = pkg.split_whitespace().collect();
27 if split.len() != 3 {
28 return Err(Error::UnknownOutput);
29 };
30
31 let explicit = ex_list_str.contains(pkg);
32
33 let Some(pkg_id) = split[0].split_once('.') else {
34 return Err(Error::UnknownOutput);
35 };
36 pkgs.push(Package {
37 id: pkg_id.0.to_string(),
38 version: split[1].to_string(),
39 explicit,
40 });
41 }
42
43 Ok(PackageList {
44 packages: pkgs,
45 manager: super::Manager::Dnf,
46 })
47 }
48
49 fn install(&self, pkgs: Vec<super::Package>) -> Result<()> {
50 let mut args = vec!["dnf".to_string(), "install".to_string(), "--assumeyes".to_string()];
51
52 for pkg in pkgs {
53 args.push(pkg.id);
54 }
55 Command::new("sudo")
56 .stdout(Stdio::inherit())
57 .args(args)
58 .spawn()?
59 .wait_with_output()?;
60 Ok(())
61 }
62}
diff --git a/src/pathinfo.rs b/src/pathinfo.rs
index 009f46a..80614cd 100644
--- a/src/pathinfo.rs
+++ b/src/pathinfo.rs
@@ -392,11 +392,16 @@ mod tests {
392 } 392 }
393 393
394 #[test] 394 #[test]
395 fn compare_to_last_modified() -> Result<()> { 395 fn compare_to_last_modified() -> color_eyre::Result<()> {
396 let mut config = Config { root: "./backup-test".to_string(), ..Default::default() }; 396
397 let cwd = std::env::current_dir()?;
398 let test_dir = format!("{}/backup-test-dir", cwd.display());
399
400 let mut config = Config::default();
401 config.root = "./backup-test".to_string();
397 config 402 config
398 .directories 403 .directories
399 .push("u:fx/code/proj/arbs/backup-test-dir".to_string()); 404 .push(format!("r:{test_dir}"));
400 405
401 create_dir_all("./backup-test-dir")?; 406 create_dir_all("./backup-test-dir")?;
402 let mut f = File::create("./backup-test-dir/size.txt")?; 407 let mut f = File::create("./backup-test-dir/size.txt")?;
@@ -414,17 +419,21 @@ mod tests {
414 let mut f = File::create("./backup-test-dir/content.txt")?; 419 let mut f = File::create("./backup-test-dir/content.txt")?;
415 f.write_all("unmodefied".as_bytes())?; 420 f.write_all("unmodefied".as_bytes())?;
416 421
417 let pi = PathInfo::from_path(&config, "u:fx/code/proj/arbs/backup-test-dir")?; 422 let pi = PathInfo::from_path(&config, format!("r:{test_dir}").as_str())?;
423
424 let nothing_full = format!("{test_dir}/nothing.txt");
425 let nothing = &nothing_full[1..nothing_full.len()];
418 426
419 let last_backup = Backup::get_last(&config)?.unwrap(); 427 let last_backup = Backup::get_last(&config)?.unwrap();
420 for file in pi.children { 428 for file in pi.children {
421 println!("test rel: {}", file.rel_location); 429 println!("test rel: {}", file.rel_location);
422 let res = if file.rel_location == "code/proj/arbs/backup-test-dir/nothing.txt" { 430 println!("nothing: {}", nothing);
431 let res = if file.rel_location == nothing {
423 Some(last_backup.id.clone()) 432 Some(last_backup.id.clone())
424 } else { 433 } else {
425 None 434 None
426 }; 435 };
427 println!("Testing {file:?}"); 436 // println!("Testing {file:?}");
428 assert_eq!( 437 assert_eq!(
429 PathInfo::compare_to_last_modified( 438 PathInfo::compare_to_last_modified(
430 &config, 439 &config,
@@ -433,7 +442,7 @@ mod tests {
433 )?, 442 )?,
434 res 443 res
435 ); 444 );
436 println!("\x1B[FTesting {file:?} ✓"); 445 // println!("\x1B[FTesting {file:?} ✓");
437 } 446 }
438 447
439 remove_dir_all("./backup-test-dir")?; 448 remove_dir_all("./backup-test-dir")?;