summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backup.rs37
-rw-r--r--src/cli.rs7
-rw-r--r--src/config.rs28
-rw-r--r--src/error.rs17
-rw-r--r--src/main.rs47
-rw-r--r--src/packages.rs13
-rw-r--r--src/pathinfo.rs110
7 files changed, 153 insertions, 106 deletions
diff --git a/src/backup.rs b/src/backup.rs
index 3d07ace..b468917 100644
--- a/src/backup.rs
+++ b/src/backup.rs
@@ -2,18 +2,18 @@ use std::{
2 fs::{create_dir_all, File}, 2 fs::{create_dir_all, File},
3 io::{Read, Write}, 3 io::{Read, Write},
4 path::PathBuf, 4 path::PathBuf,
5 time::{SystemTime, UNIX_EPOCH}, 5 time::SystemTime,
6}; 6};
7 7
8use serde::{Deserialize, Serialize}; 8use serde::{Deserialize, Serialize};
9use tracing::info; 9use tracing::{debug, info};
10use uuid::Uuid; 10use uuid::Uuid;
11 11
12use crate::{ 12use crate::{
13 config::Config, 13 config::Config,
14 error::{Error, Result}, 14 error::{Error, Result},
15 packages::{Manager, PackageList}, 15 packages::PackageList,
16 pathinfo::PathInfo, 16 pathinfo::PathInfo, send_notification,
17}; 17};
18 18
19pub type Id = String; 19pub type Id = String;
@@ -28,16 +28,20 @@ pub struct Backup {
28} 28}
29 29
30impl Backup { 30impl Backup {
31 pub fn create(config: &Config, manager: Option<Manager>) -> Result<Self> { 31 pub fn create(config: &Config) -> 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)?);
35 } 35 }
36 Ok(Self { 36 Ok(Self {
37 // TODO: UUID not really needed, maybe a shorter hash
38 id: Uuid::new_v4().to_string(), 37 id: Uuid::new_v4().to_string(),
39 timestamp: Self::get_timestamp(), 38 timestamp: SystemTime::now()
40 packages: Manager::get_manager(manager)?.get_installed()?, 39 .duration_since(SystemTime::UNIX_EPOCH)?
40 .as_secs(),
41 packages: config
42 .package_manager
43 .to_package_manager()
44 .get_installed()?,
41 files, 45 files,
42 device: config.device.clone(), 46 device: config.device.clone(),
43 }) 47 })
@@ -58,12 +62,14 @@ impl Backup {
58 path.save(&backup_root)?; 62 path.save(&backup_root)?;
59 } 63 }
60 64
65 send_notification("Backup created" , "", notify_rust::Urgency::Normal)?;
66
61 Ok(()) 67 Ok(())
62 } 68 }
63 69
64 pub fn get_last(config: &Config) -> Result<Option<Self>> { 70 pub fn get_last(config: &Config) -> Result<Option<Self>> {
65 let backup_index_root = format!("{}/index.json", config.root); 71 let backup_index_root = format!("{}/index.json", config.root);
66 info!(?backup_index_root, "backup index location:"); 72 debug!(?backup_index_root, "backup index location:");
67 let list: Vec<IndexEntry> = match Self::get_json_content(&backup_index_root) { 73 let list: Vec<IndexEntry> = match Self::get_json_content(&backup_index_root) {
68 Ok(list) => list, 74 Ok(list) => list,
69 Err(err) => { 75 Err(err) => {
@@ -74,8 +80,6 @@ impl Backup {
74 } 80 }
75 }; 81 };
76 82
77 info!(?list, "backup index:");
78
79 Ok(Some(Self::from_index( 83 Ok(Some(Self::from_index(
80 config, 84 config,
81 &list.last().ok_or(Error::BackupNotFound)?.id, 85 &list.last().ok_or(Error::BackupNotFound)?.id,
@@ -122,6 +126,8 @@ impl Backup {
122 path.restore(config, &backup_root)?; 126 path.restore(config, &backup_root)?;
123 } 127 }
124 128
129 send_notification("Backup restored" , "", notify_rust::Urgency::Normal)?;
130
125 Ok(()) 131 Ok(())
126 } 132 }
127 133
@@ -131,13 +137,6 @@ impl Backup {
131 file.read_to_string(&mut content)?; 137 file.read_to_string(&mut content)?;
132 Ok(serde_json::from_str(&content)?) 138 Ok(serde_json::from_str(&content)?)
133 } 139 }
134
135 fn get_timestamp() -> u64 {
136 SystemTime::now()
137 .duration_since(UNIX_EPOCH)
138 .unwrap()
139 .as_secs()
140 }
141} 140}
142 141
143#[derive(Debug, Clone, Serialize, Deserialize)] 142#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -165,7 +164,7 @@ impl IndexEntry {
165 164
166 f.write_all(&serde_json::to_vec(&loc)?)?; 165 f.write_all(&serde_json::to_vec(&loc)?)?;
167 } else { 166 } else {
168 create_dir_all(&config.root).unwrap(); 167 create_dir_all(&config.root)?;
169 let mut f = File::create(backup_index_root)?; 168 let mut f = File::create(backup_index_root)?;
170 f.write_all(&serde_json::to_vec(&vec![self])?)?; 169 f.write_all(&serde_json::to_vec(&vec![self])?)?;
171 }; 170 };
diff --git a/src/cli.rs b/src/cli.rs
index 1b62a84..588b6b0 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -2,8 +2,6 @@ use std::path::PathBuf;
2 2
3use clap::{Parser, Subcommand}; 3use clap::{Parser, Subcommand};
4 4
5use crate::packages::Manager;
6
7#[derive(Parser)] 5#[derive(Parser)]
8pub struct Cli { 6pub struct Cli {
9 #[arg(short, long)] 7 #[arg(short, long)]
@@ -16,10 +14,7 @@ pub struct Cli {
16#[derive(Subcommand)] 14#[derive(Subcommand)]
17pub enum Subcommands { 15pub enum Subcommands {
18 GenerateConfig, 16 GenerateConfig,
19 Save { 17 Save,
20 #[arg(short, long)]
21 package_manager: Option<Manager>,
22 },
23 Restore { 18 Restore {
24 #[arg(short, long)] 19 #[arg(short, long)]
25 package_install: bool 20 package_install: bool
diff --git a/src/config.rs b/src/config.rs
index 46d2204..848be19 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -4,6 +4,8 @@ use config::{File, Map};
4use serde::{Deserialize, Serialize}; 4use serde::{Deserialize, Serialize};
5use tracing::{debug, trace}; 5use tracing::{debug, trace};
6 6
7use crate::{error::{Error, Result}, packages::Manager};
8
7#[derive(Debug, Serialize, Deserialize)] 9#[derive(Debug, Serialize, Deserialize)]
8#[serde(default)] 10#[serde(default)]
9pub struct Config { 11pub struct Config {
@@ -11,6 +13,7 @@ pub struct Config {
11 pub directories: Vec<String>, 13 pub directories: Vec<String>,
12 pub custom_directories: Map<String, String>, 14 pub custom_directories: Map<String, String>,
13 pub device: String, 15 pub device: String,
16 pub package_manager: Manager,
14} 17}
15 18
16impl Default for Config { 19impl Default for Config {
@@ -22,17 +25,18 @@ impl Default for Config {
22 device: gethostname::gethostname() 25 device: gethostname::gethostname()
23 .into_string() 26 .into_string()
24 .expect("invalid hostname string"), 27 .expect("invalid hostname string"),
28 package_manager: Manager::from_sys().expect("couldn't get package manager"),
25 } 29 }
26 } 30 }
27} 31}
28 32
29impl Config { 33impl Config {
30 pub fn load(path: Option<PathBuf>) -> core::result::Result<Self, config::ConfigError> { 34 pub fn load(path: Option<PathBuf>) -> Result<Self> {
31 debug!("load config"); 35 debug!("load config");
32 let source = if let Some(source) = path { 36 let source = if let Some(source) = path {
33 source 37 source
34 } else { 38 } else {
35 Self::get_location() 39 Self::get_location()?
36 }; 40 };
37 41
38 let config = config::Config::builder() 42 let config = config::Config::builder()
@@ -40,14 +44,14 @@ impl Config {
40 .add_source(config::Environment::with_prefix("FXBAUP").separator("_")) 44 .add_source(config::Environment::with_prefix("FXBAUP").separator("_"))
41 .build()?; 45 .build()?;
42 46
43 let cfg = config.try_deserialize(); 47 let cfg = config.try_deserialize()?;
44 trace!(?cfg, "loaded config"); 48 trace!(?cfg, "loaded config");
45 49
46 cfg 50 Ok(cfg)
47 } 51 }
48 52
49 pub fn generate() -> crate::error::Result<()> { 53 pub fn generate() -> Result<()> {
50 let loc = Self::get_location(); 54 let loc = Self::get_location()?;
51 create_dir_all(loc.parent().unwrap())?; 55 create_dir_all(loc.parent().unwrap())?;
52 let mut f = std::fs::File::create(loc)?; 56 let mut f = std::fs::File::create(loc)?;
53 f.write_all(toml::to_string(&Self::default())?.as_bytes())?; 57 f.write_all(toml::to_string(&Self::default())?.as_bytes())?;
@@ -55,10 +59,12 @@ impl Config {
55 Ok(()) 59 Ok(())
56 } 60 }
57 61
58 fn get_location() -> PathBuf { 62 fn get_location() -> Result<PathBuf> {
59 let mut conf_dir = dirs::config_local_dir().unwrap(); 63 let Some(mut config_dir) = dirs::config_dir() else {
60 conf_dir.push("arbs"); 64 return Err(Error::NoSysDir);
61 conf_dir.push("config.toml"); 65 };
62 conf_dir 66 config_dir.push(env!("CARGO_PKG_NAME"));
67 config_dir.push("config.toml");
68 Ok(config_dir)
63 } 69 }
64} 70}
diff --git a/src/error.rs b/src/error.rs
index cb57e99..8270b45 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,3 +1,5 @@
1use tracing::error;
2
1pub type Result<T> = std::result::Result<T, Error>; 3pub type Result<T> = std::result::Result<T, Error>;
2 4
3#[derive(Debug, thiserror::Error)] 5#[derive(Debug, thiserror::Error)]
@@ -17,6 +19,10 @@ pub enum Error {
17 #[error("Requested backup not found")] 19 #[error("Requested backup not found")]
18 BackupNotFound, 20 BackupNotFound,
19 21
22 // Utils
23 #[error("System directory not found")]
24 NoSysDir,
25
20 // Packages 26 // Packages
21 #[error("Unknown Package Manger Output")] 27 #[error("Unknown Package Manger Output")]
22 UnknownOutput, 28 UnknownOutput,
@@ -26,11 +32,22 @@ pub enum Error {
26 32
27 // Deps 33 // Deps
28 #[error(transparent)] 34 #[error(transparent)]
35 Config(#[from] config::ConfigError),
36
37 #[error(transparent)]
29 SerdeJson(#[from] serde_json::Error), 38 SerdeJson(#[from] serde_json::Error),
30 39
31 #[error(transparent)] 40 #[error(transparent)]
32 TomlSerialize(#[from] toml::ser::Error), 41 TomlSerialize(#[from] toml::ser::Error),
33 42
43 #[cfg(feature = "notifications")]
44 #[error(transparent)]
45 Notify(#[from] notify_rust::error::Error),
46
47 // Rust
34 #[error(transparent)] 48 #[error(transparent)]
35 Io(#[from] std::io::Error), 49 Io(#[from] std::io::Error),
50
51 #[error(transparent)]
52 SystemTime(#[from] std::time::SystemTimeError),
36} 53}
diff --git a/src/main.rs b/src/main.rs
index 487d095..ab23ab7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,8 +2,9 @@ use backup::Backup;
2use clap::Parser; 2use clap::Parser;
3use cli::Subcommands; 3use cli::Subcommands;
4use config::Config; 4use config::Config;
5use error::Error; 5use error::{Error, Result};
6use tracing::{debug, level_filters::LevelFilter}; 6use notify_rust::Urgency;
7use tracing::{debug, error, level_filters::LevelFilter};
7use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; 8use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
8 9
9mod backup; 10mod backup;
@@ -13,9 +14,7 @@ mod error;
13mod packages; 14mod packages;
14mod pathinfo; 15mod pathinfo;
15 16
16fn main() -> color_eyre::Result<()> { 17fn main() -> Result<()> {
17 color_eyre::install()?;
18
19 let file_appender = tracing_appender::rolling::never("./", "arbs.log"); 18 let file_appender = tracing_appender::rolling::never("./", "arbs.log");
20 let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender); 19 let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender);
21 20
@@ -35,15 +34,27 @@ fn main() -> color_eyre::Result<()> {
35 ) 34 )
36 .init(); 35 .init();
37 debug!("logging initialized"); 36 debug!("logging initialized");
37
38 match run_cli() {
39 Ok(()) => { println!("OK") ; Ok(())},
40 Err(err) => {
41 error!(?err);
42 error!("{:?}", std::error::Error::source(&err));
43 send_notification("Backup Error", &err.to_string(), Urgency::Critical)?;
44 Err(err)
45 }
46 }
47}
38 48
49fn run_cli() -> Result<()> {
39 let cli = cli::Cli::parse(); 50 let cli = cli::Cli::parse();
40 51
41 let config = Config::load(cli.config)?; 52 let config = Config::load(cli.config)?;
42 53
43 match cli.subcommand { 54 match cli.subcommand {
44 Subcommands::GenerateConfig => Config::generate()?, 55 Subcommands::GenerateConfig => Config::generate()?,
45 Subcommands::Save { package_manager } => { 56 Subcommands::Save => {
46 let backup = Backup::create(&config, package_manager)?; 57 let backup = Backup::create(&config)?;
47 backup.save(&config)?; 58 backup.save(&config)?;
48 } 59 }
49 Subcommands::Restore { package_install } => { 60 Subcommands::Restore { package_install } => {
@@ -56,7 +67,27 @@ fn main() -> color_eyre::Result<()> {
56 } 67 }
57 68
58 last_backup.restore(&config)?; 69 last_backup.restore(&config)?;
59 } 70 },
60 }; 71 };
61 Ok(()) 72 Ok(())
62} 73}
74
75fn send_notification(summary: &str, body: &str, urgency: Urgency) -> Result<()> {
76 #[cfg(feature = "notifications")]
77 {
78 let Some(mut icon) = dirs::data_dir() else {
79 return Err(Error::NoSysDir);
80 };
81 icon.push(env!("CARGO_PKG_NAME"));
82 icon.push("icon.png");
83
84 notify_rust::Notification::new()
85 .summary(summary)
86 .body(body)
87 .icon(&icon.to_string_lossy())
88 .timeout(0)
89 .urgency(urgency)
90 .show()?;
91 }
92 Ok(())
93}
diff --git a/src/packages.rs b/src/packages.rs
index de818f4..41b9478 100644
--- a/src/packages.rs
+++ b/src/packages.rs
@@ -37,15 +37,12 @@ pub enum Manager {
37} 37}
38 38
39impl Manager { 39impl Manager {
40 pub fn get_manager(manager: Option<Manager>) -> Result<Box<dyn PackageManager>> { 40 pub fn from_sys() -> Result<Self> {
41 #[cfg(not(target_os = "linux"))] 41 #[cfg(not(target_os = "linux"))]
42 return Err(Error::Unsupported); 42 return Err(Error::Unsupported);
43 43
44 #[cfg(target_os = "linux")] 44 #[cfg(target_os = "linux")]
45 { 45 {
46 if let Some(man) = manager {
47 return Ok(man.to_package_manager());
48 }
49 let mut os_release = File::open("/etc/os-release")?; 46 let mut os_release = File::open("/etc/os-release")?;
50 let mut content = String::new(); 47 let mut content = String::new();
51 os_release.read_to_string(&mut content)?; 48 os_release.read_to_string(&mut content)?;
@@ -63,15 +60,15 @@ impl Manager {
63 } 60 }
64 } 61 }
65 62
66 fn from_str(value: &str) -> Result<Box<dyn PackageManager>> { 63 fn from_str(value: &str) -> Result<Self> {
67 Ok(match value { 64 Ok(match value {
68 "arch" => Box::new(Pacman), 65 "arch" => Self::Pacman,
69 "gentoo" => Box::new(Portage), 66 "gentoo" => Self::Portage,
70 _ => return Err(Error::Unsupported), 67 _ => return Err(Error::Unsupported),
71 }) 68 })
72 } 69 }
73 70
74 fn to_package_manager(&self) -> Box<dyn PackageManager> { 71 pub fn to_package_manager(&self) -> Box<dyn PackageManager> {
75 match self { 72 match self {
76 Self::Pacman => Box::new(Pacman), 73 Self::Pacman => Box::new(Pacman),
77 Self::Portage => Box::new(Portage), 74 Self::Portage => Box::new(Portage),
diff --git a/src/pathinfo.rs b/src/pathinfo.rs
index 1231ff8..009f46a 100644
--- a/src/pathinfo.rs
+++ b/src/pathinfo.rs
@@ -6,7 +6,7 @@ use std::{
6}; 6};
7 7
8use serde::{Deserialize, Serialize}; 8use serde::{Deserialize, Serialize};
9use tracing::{debug, info}; 9use tracing::{debug, info, trace};
10 10
11use crate::{ 11use crate::{
12 backup::{Backup, Id}, 12 backup::{Backup, Id},
@@ -35,7 +35,7 @@ impl PathInfo {
35 rel_location: &str, 35 rel_location: &str,
36 location_root: &LocationRoot, 36 location_root: &LocationRoot,
37 ) -> Result<Self> { 37 ) -> Result<Self> {
38 info!("Handling {rel_location}"); 38 trace!("Handling {rel_location}");
39 let path = Self::get_abs_path(&location_root.to_string(), rel_location); 39 let path = Self::get_abs_path(&location_root.to_string(), rel_location);
40 Ok(if path.is_dir() { 40 Ok(if path.is_dir() {
41 let mut last_modified = Some(String::new()); 41 let mut last_modified = Some(String::new());
@@ -83,7 +83,7 @@ impl PathInfo {
83 ) -> Result<Self> { 83 ) -> Result<Self> {
84 let last_modified = Self::compare_to_last_modified(config, location_root, rel_location)?; 84 let last_modified = Self::compare_to_last_modified(config, location_root, rel_location)?;
85 85
86 info!("From file {rel_location} ({last_modified:?})"); 86 debug!("From file {rel_location} ({last_modified:?})");
87 87
88 Ok(Self { 88 Ok(Self {
89 rel_location: rel_location.to_string(), 89 rel_location: rel_location.to_string(),
@@ -301,14 +301,15 @@ mod tests {
301 .custom_directories 301 .custom_directories
302 .insert("test".to_string(), "/usr/local/test".to_string()); 302 .insert("test".to_string(), "/usr/local/test".to_string());
303 303
304 let mut values_ok: Vec<(&str, LocationRoot)> = Vec::new(); 304 let values_ok = vec![
305 values_ok.push(("u:test", LocationRoot::User)); 305 ("u:test", LocationRoot::User),
306 values_ok.push(("s:", LocationRoot::SystemConfig)); 306 ("s:", LocationRoot::SystemConfig),
307 values_ok.push(("r:", LocationRoot::Root)); 307 ("r:", LocationRoot::Root),
308 values_ok.push(( 308 (
309 "c:test", 309 "c:test",
310 LocationRoot::Custom("/usr/local/test".to_string()), 310 LocationRoot::Custom("/usr/local/test".to_string()),
311 )); 311 ),
312 ];
312 313
313 for value in values_ok { 314 for value in values_ok {
314 println!("Testing {value:?}"); 315 println!("Testing {value:?}");
@@ -316,18 +317,19 @@ mod tests {
316 println!("\x1B[FTesting {value:?} ✓"); 317 println!("\x1B[FTesting {value:?} ✓");
317 } 318 }
318 319
319 let mut values_err: Vec<(&str, String)> = Vec::new(); 320 let values_err = vec![
320 values_err.push(( 321 (
321 "c:rest", 322 "c:rest",
322 Error::CustomDirectory("rest".to_string()).to_string(), 323 Error::CustomDirectory("rest".to_string()).to_string(),
323 )); 324 ),
324 values_err.push(("t:test/", Error::InvalidIndex("t".to_string()).to_string())); 325 ("t:test/", Error::InvalidIndex("t".to_string()).to_string()),
325 values_err.push(( 326 (
326 "test:test/usr", 327 "test:test/usr",
327 Error::InvalidIndex("test".to_string()).to_string(), 328 Error::InvalidIndex("test".to_string()).to_string(),
328 )); 329 ),
329 values_err.push(("/usr/local/test", Error::NoIndex.to_string())); 330 ("/usr/local/test", Error::NoIndex.to_string()),
330 values_err.push(("c/usr/local/test", Error::NoIndex.to_string())); 331 ("c/usr/local/test", Error::NoIndex.to_string()),
332 ];
331 333
332 for value in values_err { 334 for value in values_err {
333 println!("Testing {value:?}"); 335 println!("Testing {value:?}");
@@ -351,47 +353,47 @@ mod tests {
351 .custom_directories 353 .custom_directories
352 .insert("test".to_string(), "/usr/local/test".to_string()); 354 .insert("test".to_string(), "/usr/local/test".to_string());
353 355
354 let mut values_ok: Vec<(&str, (String, LocationRoot))> = Vec::new(); 356 let values_ok = vec![
355 values_ok.push((
356 "~/.config/nvim",
357 (".config/nvim".to_string(), LocationRoot::User),
358 ));
359 values_ok.push((
360 "u:test/.config/nvim",
361 (".config/nvim".to_string(), LocationRoot::User),
362 ));
363 values_ok.push((
364 "r:/.config/nvim",
365 (".config/nvim".to_string(), LocationRoot::Root),
366 ));
367 values_ok.push((
368 "r:/.config/nvim",
369 (".config/nvim".to_string(), LocationRoot::Root),
370 ));
371 values_ok.push((
372 "s:/.config/nvim",
373 (".config/nvim".to_string(), LocationRoot::SystemConfig),
374 ));
375 values_ok.push((
376 "c:test/.config/nvim",
377 ( 357 (
378 ".config/nvim".to_string(), 358 "~/.config/nvim",
379 LocationRoot::Custom("/usr/local/test".to_string()), 359 (".config/nvim".to_string(), LocationRoot::User),
360 ),
361 (
362 "u:test/.config/nvim",
363 (".config/nvim".to_string(), LocationRoot::User),
380 ), 364 ),
381 )); 365 (
366 "r:/.config/nvim",
367 (".config/nvim".to_string(), LocationRoot::Root),
368 ),
369 (
370 "r:/.config/nvim",
371 (".config/nvim".to_string(), LocationRoot::Root),
372 ),
373 (
374 "s:/.config/nvim",
375 (".config/nvim".to_string(), LocationRoot::SystemConfig),
376 ),
377 (
378 "c:test/.config/nvim",
379 (
380 ".config/nvim".to_string(),
381 LocationRoot::Custom("/usr/local/test".to_string()),
382 ),
383 ),
384 ];
382 385
383 for value in values_ok { 386 for value in values_ok {
384 print!("Testing {value:?}"); 387 print!("Testing {value:?}");
385 assert_eq!(PathInfo::parse_location(&value.0, &config)?, value.1); 388 assert_eq!(PathInfo::parse_location(value.0, &config)?, value.1);
386 println!("\x1B[FTesting {value:?} ✓"); 389 println!("\x1B[FTesting {value:?} ✓");
387 } 390 }
388 Ok(()) 391 Ok(())
389 } 392 }
390 393
391 #[test] 394 #[test]
392 fn compare_to_last_modified() -> color_eyre::Result<()> { 395 fn compare_to_last_modified() -> Result<()> {
393 let mut config = Config::default(); 396 let mut config = Config { root: "./backup-test".to_string(), ..Default::default() };
394 config.root = "./backup-test".to_string();
395 config 397 config
396 .directories 398 .directories
397 .push("u:fx/code/proj/arbs/backup-test-dir".to_string()); 399 .push("u:fx/code/proj/arbs/backup-test-dir".to_string());
@@ -404,7 +406,7 @@ mod tests {
404 let mut f = File::create("./backup-test-dir/nothing.txt")?; 406 let mut f = File::create("./backup-test-dir/nothing.txt")?;
405 f.write_all("unmodified".as_bytes())?; 407 f.write_all("unmodified".as_bytes())?;
406 408
407 let backup = Backup::create(&config, None)?; 409 let backup = Backup::create(&config)?;
408 backup.save(&config)?; 410 backup.save(&config)?;
409 411
410 let mut f = File::create("./backup-test-dir/size.txt")?; 412 let mut f = File::create("./backup-test-dir/size.txt")?;