diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backup.rs | 17 | ||||
-rw-r--r-- | src/cli.rs | 25 | ||||
-rw-r--r-- | src/config.rs | 30 | ||||
-rw-r--r-- | src/error.rs | 12 | ||||
-rw-r--r-- | src/main.rs | 42 | ||||
-rw-r--r-- | src/packages.rs | 85 | ||||
-rw-r--r-- | src/packages/pacman.rs | 13 | ||||
-rw-r--r-- | src/packages/portage.rs | 4 | ||||
-rw-r--r-- | src/pathinfo.rs | 41 |
9 files changed, 208 insertions, 61 deletions
diff --git a/src/backup.rs b/src/backup.rs index e463593..f9de139 100644 --- a/src/backup.rs +++ b/src/backup.rs | |||
@@ -12,7 +12,7 @@ use uuid::Uuid; | |||
12 | use crate::{ | 12 | use crate::{ |
13 | config::Config, | 13 | config::Config, |
14 | error::{Error, Result}, | 14 | error::{Error, Result}, |
15 | packages::Package, | 15 | packages::{Manager, PackageList}, |
16 | pathinfo::PathInfo, | 16 | pathinfo::PathInfo, |
17 | }; | 17 | }; |
18 | 18 | ||
@@ -22,13 +22,13 @@ pub type Id = String; | |||
22 | pub struct Backup { | 22 | pub struct Backup { |
23 | pub id: String, | 23 | pub id: String, |
24 | pub timestamp: u64, | 24 | pub timestamp: u64, |
25 | packages: Vec<Package>, | 25 | pub packages: PackageList, |
26 | pub files: Vec<PathInfo>, | 26 | pub files: Vec<PathInfo>, |
27 | device: String, | 27 | pub device: String, |
28 | } | 28 | } |
29 | 29 | ||
30 | impl Backup { | 30 | impl Backup { |
31 | pub fn create(config: &Config, packages: Vec<Package>) -> Result<Self> { | 31 | pub fn create(config: &Config, manager: Option<Manager>) -> Result<Self> { |
32 | let mut files: Vec<PathInfo> = Vec::new(); | 32 | let mut files: Vec<PathInfo> = Vec::new(); |
33 | for dir in &config.directories { | 33 | for dir in &config.directories { |
34 | files.push(PathInfo::from_path(config, dir)?); | 34 | files.push(PathInfo::from_path(config, dir)?); |
@@ -37,7 +37,7 @@ impl Backup { | |||
37 | // TODO: UUID not really needed, maybe a shorter hash | 37 | // TODO: UUID not really needed, maybe a shorter hash |
38 | id: Uuid::new_v4().to_string(), | 38 | id: Uuid::new_v4().to_string(), |
39 | timestamp: Self::get_timestamp(), | 39 | timestamp: Self::get_timestamp(), |
40 | packages, | 40 | packages: Manager::get_manager(manager)?.get_installed()?, |
41 | files, | 41 | files, |
42 | device: config.device.clone(), | 42 | device: config.device.clone(), |
43 | }) | 43 | }) |
@@ -62,6 +62,7 @@ impl Backup { | |||
62 | 62 | ||
63 | pub fn get_last(config: &Config) -> Result<Option<Self>> { | 63 | pub fn get_last(config: &Config) -> Result<Option<Self>> { |
64 | let backup_index_root = format!("{}/index.json", config.root); | 64 | let backup_index_root = format!("{}/index.json", config.root); |
65 | info!(?backup_index_root, "backup index location:"); | ||
65 | let list: Vec<IndexEntry> = match Self::get_json_content(&backup_index_root) { | 66 | let list: Vec<IndexEntry> = match Self::get_json_content(&backup_index_root) { |
66 | Ok(list) => list, | 67 | Ok(list) => list, |
67 | Err(err) => { | 68 | Err(err) => { |
@@ -72,6 +73,8 @@ impl Backup { | |||
72 | } | 73 | } |
73 | }; | 74 | }; |
74 | 75 | ||
76 | info!(?list, "backup index:"); | ||
77 | |||
75 | Ok(Some(Self::from_index( | 78 | Ok(Some(Self::from_index( |
76 | config, | 79 | config, |
77 | &list.last().ok_or(Error::BackupNotFound)?.id, | 80 | &list.last().ok_or(Error::BackupNotFound)?.id, |
@@ -109,6 +112,10 @@ impl Backup { | |||
109 | format!("{loc}/{rel_location}") | 112 | format!("{loc}/{rel_location}") |
110 | } | 113 | } |
111 | 114 | ||
115 | pub fn restore(&self) { | ||
116 | todo!() | ||
117 | } | ||
118 | |||
112 | fn get_json_content<T: for<'a> Deserialize<'a>>(path: &str) -> Result<T> { | 119 | fn get_json_content<T: for<'a> Deserialize<'a>>(path: &str) -> Result<T> { |
113 | let mut file = File::open(path)?; | 120 | let mut file = File::open(path)?; |
114 | let mut content = String::new(); | 121 | let mut content = String::new(); |
diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..6ffe03f --- /dev/null +++ b/src/cli.rs | |||
@@ -0,0 +1,25 @@ | |||
1 | use std::path::PathBuf; | ||
2 | |||
3 | use clap::{Parser, Subcommand}; | ||
4 | |||
5 | use crate::packages::Manager; | ||
6 | |||
7 | #[derive(Parser)] | ||
8 | pub struct Cli { | ||
9 | #[arg(short, long)] | ||
10 | pub config: Option<PathBuf>, | ||
11 | |||
12 | #[command(subcommand)] | ||
13 | pub subcommand: Subcommands, | ||
14 | } | ||
15 | |||
16 | #[derive(Subcommand)] | ||
17 | pub enum Subcommands { | ||
18 | GenerateConfig, | ||
19 | Save { | ||
20 | #[arg(short, long)] | ||
21 | package_manager: Option<Manager>, | ||
22 | }, | ||
23 | Restore, | ||
24 | } | ||
25 | |||
diff --git a/src/config.rs b/src/config.rs index 13dd0e4..46d2204 100644 --- a/src/config.rs +++ b/src/config.rs | |||
@@ -1,3 +1,5 @@ | |||
1 | use std::{fs::create_dir_all, io::Write, path::PathBuf}; | ||
2 | |||
1 | use config::{File, Map}; | 3 | use config::{File, Map}; |
2 | use serde::{Deserialize, Serialize}; | 4 | use serde::{Deserialize, Serialize}; |
3 | use tracing::{debug, trace}; | 5 | use tracing::{debug, trace}; |
@@ -6,7 +8,6 @@ use tracing::{debug, trace}; | |||
6 | #[serde(default)] | 8 | #[serde(default)] |
7 | pub struct Config { | 9 | pub struct Config { |
8 | pub root: String, | 10 | pub root: String, |
9 | pub user: Vec<String>, | ||
10 | pub directories: Vec<String>, | 11 | pub directories: Vec<String>, |
11 | pub custom_directories: Map<String, String>, | 12 | pub custom_directories: Map<String, String>, |
12 | pub device: String, | 13 | pub device: String, |
@@ -16,7 +17,6 @@ impl Default for Config { | |||
16 | fn default() -> Self { | 17 | fn default() -> Self { |
17 | Self { | 18 | Self { |
18 | root: "/mnt/backup".to_string(), | 19 | root: "/mnt/backup".to_string(), |
19 | user: vec![], | ||
20 | directories: vec![], | 20 | directories: vec![], |
21 | custom_directories: Map::new(), | 21 | custom_directories: Map::new(), |
22 | device: gethostname::gethostname() | 22 | device: gethostname::gethostname() |
@@ -27,10 +27,16 @@ impl Default for Config { | |||
27 | } | 27 | } |
28 | 28 | ||
29 | impl Config { | 29 | impl Config { |
30 | pub fn load() -> Result<Self, config::ConfigError> { | 30 | pub fn load(path: Option<PathBuf>) -> core::result::Result<Self, config::ConfigError> { |
31 | debug!("load config"); | 31 | debug!("load config"); |
32 | let source = if let Some(source) = path { | ||
33 | source | ||
34 | } else { | ||
35 | Self::get_location() | ||
36 | }; | ||
37 | |||
32 | let config = config::Config::builder() | 38 | let config = config::Config::builder() |
33 | .add_source(File::with_name("config.toml").required(false)) | 39 | .add_source(File::with_name(&source.to_string_lossy()).required(false)) |
34 | .add_source(config::Environment::with_prefix("FXBAUP").separator("_")) | 40 | .add_source(config::Environment::with_prefix("FXBAUP").separator("_")) |
35 | .build()?; | 41 | .build()?; |
36 | 42 | ||
@@ -39,4 +45,20 @@ impl Config { | |||
39 | 45 | ||
40 | cfg | 46 | cfg |
41 | } | 47 | } |
48 | |||
49 | pub fn generate() -> crate::error::Result<()> { | ||
50 | let loc = Self::get_location(); | ||
51 | create_dir_all(loc.parent().unwrap())?; | ||
52 | let mut f = std::fs::File::create(loc)?; | ||
53 | f.write_all(toml::to_string(&Self::default())?.as_bytes())?; | ||
54 | |||
55 | Ok(()) | ||
56 | } | ||
57 | |||
58 | fn get_location() -> PathBuf { | ||
59 | let mut conf_dir = dirs::config_local_dir().unwrap(); | ||
60 | conf_dir.push("arbs"); | ||
61 | conf_dir.push("config.toml"); | ||
62 | conf_dir | ||
63 | } | ||
42 | } | 64 | } |
diff --git a/src/error.rs b/src/error.rs index 0cf4dca..e24c3b1 100644 --- a/src/error.rs +++ b/src/error.rs | |||
@@ -14,9 +14,6 @@ pub enum Error { | |||
14 | #[error("invalid directory '{0}'")] | 14 | #[error("invalid directory '{0}'")] |
15 | InvalidDirectory(String), | 15 | InvalidDirectory(String), |
16 | 16 | ||
17 | #[error("Only exactly one user allowed in config")] | ||
18 | MultiUser, | ||
19 | |||
20 | #[error("Requested backup not found")] | 17 | #[error("Requested backup not found")] |
21 | BackupNotFound, | 18 | BackupNotFound, |
22 | 19 | ||
@@ -24,12 +21,21 @@ pub enum Error { | |||
24 | #[error("Unknown Package Manger Output")] | 21 | #[error("Unknown Package Manger Output")] |
25 | UnknownOutput, | 22 | UnknownOutput, |
26 | 23 | ||
24 | #[error("Unsupported os/distro")] | ||
25 | Unsupported, | ||
26 | |||
27 | #[error("json: {source}")] | 27 | #[error("json: {source}")] |
28 | SerdeJson { | 28 | SerdeJson { |
29 | #[from] | 29 | #[from] |
30 | source: serde_json::Error, | 30 | source: serde_json::Error, |
31 | }, | 31 | }, |
32 | 32 | ||
33 | #[error("toml serializer: {source}")] | ||
34 | TomlSerialize { | ||
35 | #[from] | ||
36 | source: toml::ser::Error, | ||
37 | }, | ||
38 | |||
33 | #[error("io: {source}")] | 39 | #[error("io: {source}")] |
34 | Io { | 40 | Io { |
35 | #[from] | 41 | #[from] |
diff --git a/src/main.rs b/src/main.rs index 1284e0c..7393af9 100644 --- a/src/main.rs +++ b/src/main.rs | |||
@@ -1,10 +1,13 @@ | |||
1 | use backup::Backup; | 1 | use backup::Backup; |
2 | use clap::Parser; | ||
3 | use cli::Subcommands; | ||
2 | use config::Config; | 4 | use config::Config; |
3 | use packages::{pacman::Pacman, PackageManager}; | 5 | use error::Error; |
4 | use tracing::{debug, info, level_filters::LevelFilter}; | 6 | use tracing::{debug, level_filters::LevelFilter}; |
5 | use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; | 7 | use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; |
6 | 8 | ||
7 | mod backup; | 9 | mod backup; |
10 | mod cli; | ||
8 | mod config; | 11 | mod config; |
9 | mod error; | 12 | mod error; |
10 | mod packages; | 13 | mod packages; |
@@ -13,7 +16,7 @@ mod pathinfo; | |||
13 | fn main() -> color_eyre::Result<()> { | 16 | fn main() -> color_eyre::Result<()> { |
14 | color_eyre::install()?; | 17 | color_eyre::install()?; |
15 | 18 | ||
16 | let file_appender = tracing_appender::rolling::never("./", "arps.log"); | 19 | let file_appender = tracing_appender::rolling::never("./", "arbs.log"); |
17 | let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender); | 20 | let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender); |
18 | 21 | ||
19 | tracing_subscriber::registry() | 22 | tracing_subscriber::registry() |
@@ -33,19 +36,24 @@ fn main() -> color_eyre::Result<()> { | |||
33 | .init(); | 36 | .init(); |
34 | debug!("logging initialized"); | 37 | debug!("logging initialized"); |
35 | 38 | ||
36 | let mut cfg = Config::load()?; | 39 | let cli = cli::Cli::parse(); |
37 | cfg.user.push("fx".to_string()); | 40 | |
38 | cfg.directories.push("~/.config/nvim".to_string()); | 41 | let config = Config::load(cli.config)?; |
39 | cfg.root = "./backup".to_string(); | 42 | |
40 | 43 | match cli.subcommand { | |
41 | let pacman = Pacman; | 44 | Subcommands::GenerateConfig => Config::generate()?, |
42 | let pkgs = pacman.get_installed()?; | 45 | Subcommands::Save { package_manager } => { |
43 | let backup = Backup::create(&cfg, pkgs); | 46 | let backup = Backup::create(&config, package_manager)?; |
44 | // info!(?backup); | 47 | backup.save(&config)?; |
45 | // pacman.install(vec![Package { | 48 | } |
46 | // id: "lapce".to_string(), | 49 | Subcommands::Restore => { |
47 | // version: "0.4.2-1".to_string(), | 50 | let Some(last_backup) = Backup::get_last(&config)? else { |
48 | // explicit: true, | 51 | return Err(Error::BackupNotFound)?; |
49 | // }])?; | 52 | }; |
53 | |||
54 | last_backup.packages.install()?; | ||
55 | last_backup.restore(); | ||
56 | } | ||
57 | }; | ||
50 | Ok(()) | 58 | Ok(()) |
51 | } | 59 | } |
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 | } |
diff --git a/src/packages/pacman.rs b/src/packages/pacman.rs index e10c6fb..0ad463b 100644 --- a/src/packages/pacman.rs +++ b/src/packages/pacman.rs | |||
@@ -1,13 +1,13 @@ | |||
1 | use std::process::{Command, Stdio}; | 1 | use std::process::{Command, Stdio}; |
2 | 2 | ||
3 | use super::{Package, PackageManager}; | 3 | use super::{Package, PackageList, PackageManager}; |
4 | 4 | ||
5 | use crate::error::{Error, Result}; | 5 | use crate::error::{Error, Result}; |
6 | 6 | ||
7 | pub struct Pacman; | 7 | pub struct Pacman; |
8 | 8 | ||
9 | impl PackageManager for Pacman { | 9 | impl PackageManager for Pacman { |
10 | fn get_installed(&self) -> Result<Vec<super::Package>> { | 10 | fn get_installed(&self) -> Result<PackageList> { |
11 | let pm_pkgs = Command::new("pacman").args(["-Q"]).output().unwrap(); | 11 | let pm_pkgs = Command::new("pacman").args(["-Q"]).output().unwrap(); |
12 | let pm_e_pkgs = Command::new("pacman") | 12 | let pm_e_pkgs = Command::new("pacman") |
13 | .args(["-Q", "--explicit"]) | 13 | .args(["-Q", "--explicit"]) |
@@ -37,16 +37,19 @@ impl PackageManager for Pacman { | |||
37 | }); | 37 | }); |
38 | } | 38 | } |
39 | 39 | ||
40 | Ok(pkgs) | 40 | Ok(PackageList { |
41 | packages: pkgs, | ||
42 | manager: super::Manager::Pacman, | ||
43 | }) | ||
41 | } | 44 | } |
42 | 45 | ||
43 | fn install(&self, pkgs: Vec<super::Package>) -> Result<()> { | 46 | fn install(&self, pkgs: Vec<super::Package>) -> Result<()> { |
44 | let mut args = vec!["--noconfirm".to_string(), "-S".to_string()]; | 47 | let mut args = vec!["pacman".to_string(), "--noconfirm".to_string(), "-S".to_string()]; |
45 | 48 | ||
46 | for pkg in pkgs { | 49 | for pkg in pkgs { |
47 | args.push(pkg.id); | 50 | args.push(pkg.id); |
48 | } | 51 | } |
49 | Command::new("pacman") | 52 | Command::new("doas") |
50 | .stdout(Stdio::inherit()) | 53 | .stdout(Stdio::inherit()) |
51 | .args(args) | 54 | .args(args) |
52 | .spawn()? | 55 | .spawn()? |
diff --git a/src/packages/portage.rs b/src/packages/portage.rs index f9a760b..7fa09a8 100644 --- a/src/packages/portage.rs +++ b/src/packages/portage.rs | |||
@@ -1,11 +1,11 @@ | |||
1 | use tracing::error; | 1 | use tracing::error; |
2 | 2 | ||
3 | use super::PackageManager; | 3 | use super::{PackageList, PackageManager}; |
4 | 4 | ||
5 | pub struct Portage; | 5 | pub struct Portage; |
6 | 6 | ||
7 | impl PackageManager for Portage { | 7 | impl PackageManager for Portage { |
8 | fn get_installed(&self) -> crate::error::Result<Vec<super::Package>> { | 8 | fn get_installed(&self) -> crate::error::Result<PackageList> { |
9 | todo!() | 9 | todo!() |
10 | } | 10 | } |
11 | 11 | ||
diff --git a/src/pathinfo.rs b/src/pathinfo.rs index 8b1ca2f..03b8a6b 100644 --- a/src/pathinfo.rs +++ b/src/pathinfo.rs | |||
@@ -120,7 +120,8 @@ impl PathInfo { | |||
120 | let old_path = modified_backup.get_absolute_file_location(config, &last_file.rel_location); | 120 | let old_path = modified_backup.get_absolute_file_location(config, &last_file.rel_location); |
121 | let new_path = format!("{location_root}/{rel_location}"); | 121 | let new_path = format!("{location_root}/{rel_location}"); |
122 | 122 | ||
123 | let mut old = File::open(old_path)?; let mut new = File::open(new_path)?; | 123 | let mut old = File::open(old_path)?; |
124 | let mut new = File::open(new_path)?; | ||
124 | 125 | ||
125 | let old_len = old.metadata()?.len(); | 126 | let old_len = old.metadata()?.len(); |
126 | let new_len = new.metadata()?.len(); | 127 | let new_len = new.metadata()?.len(); |
@@ -195,12 +196,9 @@ impl PathInfo { | |||
195 | return Err(Error::InvalidDirectory(value.to_string())); | 196 | return Err(Error::InvalidDirectory(value.to_string())); |
196 | }; | 197 | }; |
197 | if split.0.starts_with('~') { | 198 | if split.0.starts_with('~') { |
198 | if config.user.len() != 1 { | ||
199 | return Err(Error::MultiUser); | ||
200 | } | ||
201 | return Ok(( | 199 | return Ok(( |
202 | split.1.to_string(), | 200 | split.1.to_string(), |
203 | LocationRoot::User(config.user[0].clone()), | 201 | LocationRoot::User, |
204 | )); | 202 | )); |
205 | }; | 203 | }; |
206 | Ok(( | 204 | Ok(( |
@@ -212,18 +210,22 @@ impl PathInfo { | |||
212 | 210 | ||
213 | #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] | 211 | #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] |
214 | pub enum LocationRoot { | 212 | pub enum LocationRoot { |
215 | User(String), | 213 | User, |
216 | Custom(String), | 214 | Custom(String), |
217 | SystemSettings, | 215 | SystemConfig, |
216 | UserConfig, | ||
218 | Root, | 217 | Root, |
219 | } | 218 | } |
220 | 219 | ||
221 | impl Display for LocationRoot { | 220 | impl Display for LocationRoot { |
222 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | 221 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
223 | match self { | 222 | match self { |
224 | LocationRoot::User(user) => write!(f, "/home/{user}"), | 223 | LocationRoot::User => write!(f, "{}", dirs::home_dir().unwrap().to_string_lossy()), |
225 | LocationRoot::Custom(loc) => write!(f, "{loc}"), | 224 | LocationRoot::Custom(loc) => write!(f, "{loc}"), |
226 | LocationRoot::SystemSettings => write!(f, "/etc"), | 225 | LocationRoot::SystemConfig => write!(f, "/etc"), |
226 | LocationRoot::UserConfig => { | ||
227 | write!(f, "{}", dirs::config_local_dir().unwrap().to_string_lossy()) | ||
228 | } | ||
227 | LocationRoot::Root => write!(f, "/"), | 229 | LocationRoot::Root => write!(f, "/"), |
228 | } | 230 | } |
229 | } | 231 | } |
@@ -236,8 +238,9 @@ impl LocationRoot { | |||
236 | return Err(Error::NoIndex); | 238 | return Err(Error::NoIndex); |
237 | }; | 239 | }; |
238 | match split_op.0 { | 240 | match split_op.0 { |
239 | "u" => Ok(Self::User(split_op.1.to_string())), | 241 | "u" => Ok(Self::User), |
240 | "s" => Ok(Self::SystemSettings), | 242 | "s" => Ok(Self::SystemConfig), |
243 | "d" => Ok(Self::UserConfig), | ||
241 | "r" => Ok(Self::Root), | 244 | "r" => Ok(Self::Root), |
242 | "c" => Ok(Self::Custom( | 245 | "c" => Ok(Self::Custom( |
243 | config | 246 | config |
@@ -262,7 +265,6 @@ mod tests { | |||
262 | backup::Backup, | 265 | backup::Backup, |
263 | config::Config, | 266 | config::Config, |
264 | error::{Error, Result}, | 267 | error::{Error, Result}, |
265 | packages::{pacman::Pacman, PackageManager}, | ||
266 | }; | 268 | }; |
267 | 269 | ||
268 | use super::LocationRoot; | 270 | use super::LocationRoot; |
@@ -276,8 +278,8 @@ mod tests { | |||
276 | .insert("test".to_string(), "/usr/local/test".to_string()); | 278 | .insert("test".to_string(), "/usr/local/test".to_string()); |
277 | 279 | ||
278 | let mut values_ok: Vec<(&str, LocationRoot)> = Vec::new(); | 280 | let mut values_ok: Vec<(&str, LocationRoot)> = Vec::new(); |
279 | values_ok.push(("u:test", LocationRoot::User("test".to_string()))); | 281 | values_ok.push(("u:test", LocationRoot::User)); |
280 | values_ok.push(("s:", LocationRoot::SystemSettings)); | 282 | values_ok.push(("s:", LocationRoot::SystemConfig)); |
281 | values_ok.push(("r:", LocationRoot::Root)); | 283 | values_ok.push(("r:", LocationRoot::Root)); |
282 | values_ok.push(( | 284 | values_ok.push(( |
283 | "c:test", | 285 | "c:test", |
@@ -321,7 +323,6 @@ mod tests { | |||
321 | #[test] | 323 | #[test] |
322 | fn parse_location() -> Result<()> { | 324 | fn parse_location() -> Result<()> { |
323 | let mut config = Config::default(); | 325 | let mut config = Config::default(); |
324 | config.user.push("test".to_string()); | ||
325 | config | 326 | config |
326 | .custom_directories | 327 | .custom_directories |
327 | .insert("test".to_string(), "/usr/local/test".to_string()); | 328 | .insert("test".to_string(), "/usr/local/test".to_string()); |
@@ -331,14 +332,14 @@ mod tests { | |||
331 | "~/.config/nvim", | 332 | "~/.config/nvim", |
332 | ( | 333 | ( |
333 | ".config/nvim".to_string(), | 334 | ".config/nvim".to_string(), |
334 | LocationRoot::User("test".to_string()), | 335 | LocationRoot::User, |
335 | ), | 336 | ), |
336 | )); | 337 | )); |
337 | values_ok.push(( | 338 | values_ok.push(( |
338 | "u:test/.config/nvim", | 339 | "u:test/.config/nvim", |
339 | ( | 340 | ( |
340 | ".config/nvim".to_string(), | 341 | ".config/nvim".to_string(), |
341 | LocationRoot::User("test".to_string()), | 342 | LocationRoot::User, |
342 | ), | 343 | ), |
343 | )); | 344 | )); |
344 | values_ok.push(( | 345 | values_ok.push(( |
@@ -351,7 +352,7 @@ mod tests { | |||
351 | )); | 352 | )); |
352 | values_ok.push(( | 353 | values_ok.push(( |
353 | "s:/.config/nvim", | 354 | "s:/.config/nvim", |
354 | (".config/nvim".to_string(), LocationRoot::SystemSettings), | 355 | (".config/nvim".to_string(), LocationRoot::SystemConfig), |
355 | )); | 356 | )); |
356 | values_ok.push(( | 357 | values_ok.push(( |
357 | "c:test/.config/nvim", | 358 | "c:test/.config/nvim", |
@@ -385,9 +386,7 @@ mod tests { | |||
385 | let mut f = File::create("./backup-test-dir/nothing.txt")?; | 386 | let mut f = File::create("./backup-test-dir/nothing.txt")?; |
386 | f.write_all("unmodified".as_bytes())?; | 387 | f.write_all("unmodified".as_bytes())?; |
387 | 388 | ||
388 | let pacman = Pacman; | 389 | let backup = Backup::create(&config, None)?; |
389 | let pkgs = pacman.get_installed()?; | ||
390 | let backup = Backup::create(&config, pkgs)?; | ||
391 | backup.save(&config)?; | 390 | backup.save(&config)?; |
392 | 391 | ||
393 | let mut f = File::create("./backup-test-dir/size.txt")?; | 392 | let mut f = File::create("./backup-test-dir/size.txt")?; |