mirror of
https://github.com/qwjyh/xdbm
synced 2024-12-05 04:51:04 +09:00
Compare commits
2 commits
bc3939c9bc
...
8b0dbb2314
Author | SHA1 | Date | |
---|---|---|---|
8b0dbb2314 | |||
772689ab6a |
4 changed files with 43 additions and 31 deletions
|
@ -33,22 +33,27 @@ pub struct BackupTarget {
|
||||||
/// Use `String` for serialization/deserialization.
|
/// Use `String` for serialization/deserialization.
|
||||||
pub storage: String,
|
pub storage: String,
|
||||||
/// Relative path to the `storage`.
|
/// Relative path to the `storage`.
|
||||||
pub path: PathBuf,
|
pub path: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BackupTarget {
|
impl BackupTarget {
|
||||||
pub fn new(storage_name: String, relative_path: PathBuf) -> Self {
|
pub fn new(storage_name: String, relative_path: PathBuf) -> Result<Self> {
|
||||||
BackupTarget {
|
let relative_path = relative_path
|
||||||
|
.components()
|
||||||
|
.map(|c| c.as_os_str().to_str().map(|s| s.to_owned()))
|
||||||
|
.collect::<Option<_>>()
|
||||||
|
.context("Path contains non-utf8 character")?;
|
||||||
|
Ok(BackupTarget {
|
||||||
storage: storage_name,
|
storage: storage_name,
|
||||||
path: relative_path,
|
path: relative_path,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get full path of the [`BackupTarget`].
|
/// Get full path of the [`BackupTarget`].
|
||||||
pub fn path(&self, storages: &Storages, device: &Device) -> Option<PathBuf> {
|
pub fn path(&self, storages: &Storages, device: &Device) -> Option<PathBuf> {
|
||||||
let parent = storages.get(&self.storage).unwrap();
|
let parent = storages.get(&self.storage).unwrap();
|
||||||
let parent_path = parent.mount_path(device)?;
|
let parent_path = parent.mount_path(device)?;
|
||||||
Some(parent_path.join(self.path.clone()))
|
Some(parent_path.join(self.path.clone().iter().collect::<PathBuf>()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +180,7 @@ impl Backup {
|
||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn device<'a>(&'a self, devices: &'a [Device]) -> Option<&Device> {
|
pub fn device<'a>(&'a self, devices: &'a [Device]) -> Option<&'a Device> {
|
||||||
devices.iter().find(|dev| dev.name() == self.device)
|
devices.iter().find(|dev| dev.name() == self.device)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,8 +89,8 @@ fn new_backup(
|
||||||
Ok(Backup::new(
|
Ok(Backup::new(
|
||||||
name,
|
name,
|
||||||
device.name(),
|
device.name(),
|
||||||
src_target,
|
src_target?,
|
||||||
dest_target,
|
dest_target?,
|
||||||
command,
|
command,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -361,9 +361,9 @@ mod test {
|
||||||
&storages,
|
&storages,
|
||||||
)?;
|
)?;
|
||||||
assert!(backup.source().storage == "online");
|
assert!(backup.source().storage == "online");
|
||||||
assert_eq!(backup.source().path, PathBuf::from("docs"));
|
assert_eq!(backup.source().path, vec!["docs"]);
|
||||||
assert!(backup.destination().storage == "online");
|
assert!(backup.destination().storage == "online");
|
||||||
assert!(backup.destination().path == PathBuf::from("tmp"));
|
assert!(backup.destination().path == vec!["tmp"]);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,7 +146,7 @@ fn parent_backups<'a>(
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::path::PathBuf;
|
use std::{path::PathBuf, vec};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backups::{self, ExternallyInvoked},
|
backups::{self, ExternallyInvoked},
|
||||||
|
@ -201,11 +201,11 @@ mod test {
|
||||||
device1.name().to_string(),
|
device1.name().to_string(),
|
||||||
backups::BackupTarget {
|
backups::BackupTarget {
|
||||||
storage: "storage_1".to_string(),
|
storage: "storage_1".to_string(),
|
||||||
path: PathBuf::from("bar"),
|
path: vec!["bar".to_string()],
|
||||||
},
|
},
|
||||||
backups::BackupTarget {
|
backups::BackupTarget {
|
||||||
storage: "storage_1".to_string(),
|
storage: "storage_1".to_string(),
|
||||||
path: PathBuf::from("hoge"),
|
path: vec!["hoge".to_string()],
|
||||||
},
|
},
|
||||||
backups::BackupCommand::ExternallyInvoked(ExternallyInvoked::new(
|
backups::BackupCommand::ExternallyInvoked(ExternallyInvoked::new(
|
||||||
"cmd".to_string(),
|
"cmd".to_string(),
|
||||||
|
@ -217,11 +217,11 @@ mod test {
|
||||||
device2.name().to_string(),
|
device2.name().to_string(),
|
||||||
backups::BackupTarget {
|
backups::BackupTarget {
|
||||||
storage: "storage_1".to_string(),
|
storage: "storage_1".to_string(),
|
||||||
path: PathBuf::from(""),
|
path: vec!["".to_string()],
|
||||||
},
|
},
|
||||||
backups::BackupTarget {
|
backups::BackupTarget {
|
||||||
storage: "storage_3".to_string(),
|
storage: "storage_3".to_string(),
|
||||||
path: PathBuf::from("foo"),
|
path: vec!["foo".to_string()],
|
||||||
},
|
},
|
||||||
backups::BackupCommand::ExternallyInvoked(ExternallyInvoked::new(
|
backups::BackupCommand::ExternallyInvoked(ExternallyInvoked::new(
|
||||||
"cmd".to_string(),
|
"cmd".to_string(),
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::{collections::BTreeMap, fmt, path};
|
use std::{collections::BTreeMap, fmt, path};
|
||||||
|
|
||||||
use crate::devices;
|
use crate::devices;
|
||||||
|
@ -17,7 +18,7 @@ pub struct Directory {
|
||||||
/// ID of parent storage.
|
/// ID of parent storage.
|
||||||
parent: String,
|
parent: String,
|
||||||
/// Relative path to the parent storage.
|
/// Relative path to the parent storage.
|
||||||
relative_path: path::PathBuf,
|
relative_path: Vec<String>,
|
||||||
pub notes: String,
|
pub notes: String,
|
||||||
/// [`devices::Device`] name and localinfo pairs.
|
/// [`devices::Device`] name and localinfo pairs.
|
||||||
local_infos: BTreeMap<String, LocalInfo>,
|
local_infos: BTreeMap<String, LocalInfo>,
|
||||||
|
@ -34,14 +35,19 @@ impl Directory {
|
||||||
relative_path: path::PathBuf,
|
relative_path: path::PathBuf,
|
||||||
notes: String,
|
notes: String,
|
||||||
local_infos: BTreeMap<String, LocalInfo>,
|
local_infos: BTreeMap<String, LocalInfo>,
|
||||||
) -> Directory {
|
) -> Result<Directory> {
|
||||||
Directory {
|
let relative_path = relative_path
|
||||||
|
.components()
|
||||||
|
.map(|c| c.as_os_str().to_str().map(|s| s.to_owned()))
|
||||||
|
.collect::<Option<Vec<_>>>()
|
||||||
|
.context("Path contains non-utf8 character")?;
|
||||||
|
Ok(Directory {
|
||||||
name,
|
name,
|
||||||
parent,
|
parent,
|
||||||
relative_path,
|
relative_path,
|
||||||
notes,
|
notes,
|
||||||
local_infos,
|
local_infos,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_from_device_path(
|
pub fn try_from_device_path(
|
||||||
|
@ -56,23 +62,23 @@ impl Directory {
|
||||||
.context("Failed to compare diff of paths")?;
|
.context("Failed to compare diff of paths")?;
|
||||||
trace!("Selected parent: {}", parent.name());
|
trace!("Selected parent: {}", parent.name());
|
||||||
let local_info = LocalInfo::new(alias, path);
|
let local_info = LocalInfo::new(alias, path);
|
||||||
Ok(Directory::new(
|
Directory::new(
|
||||||
name,
|
name,
|
||||||
parent.name().to_string(),
|
parent.name().to_string(),
|
||||||
diff_path,
|
diff_path,
|
||||||
notes,
|
notes,
|
||||||
BTreeMap::from([(device.name(), local_info)]),
|
BTreeMap::from([(device.name(), local_info)]),
|
||||||
))
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_note(self, notes: String) -> Directory {
|
pub fn update_note(self, notes: String) -> Directory {
|
||||||
Directory::new(
|
Directory {
|
||||||
self.name,
|
name: self.name,
|
||||||
self.parent,
|
parent: self.parent,
|
||||||
self.relative_path,
|
relative_path: self.relative_path,
|
||||||
notes,
|
notes,
|
||||||
self.local_infos,
|
local_infos: self.local_infos,
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve mount path of directory with current device.
|
/// Resolve mount path of directory with current device.
|
||||||
|
@ -82,7 +88,7 @@ impl Directory {
|
||||||
.context("Can't find parent storage")?
|
.context("Can't find parent storage")?
|
||||||
.mount_path(device)
|
.mount_path(device)
|
||||||
.context("Can't find mount path")?;
|
.context("Can't find mount path")?;
|
||||||
Ok(parent_mount_path.join(self.relative_path.clone()))
|
Ok(parent_mount_path.join(self.relative_path.clone().iter().collect::<PathBuf>()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +127,7 @@ impl StorageExt for Directory {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get parent `&Storage` of directory.
|
// Get parent `&Storage` of directory.
|
||||||
fn parent<'a>(&'a self, storages: &'a Storages) -> Option<&Storage> {
|
fn parent<'a>(&'a self, storages: &'a Storages) -> Option<&'a Storage> {
|
||||||
storages.get(&self.parent)
|
storages.get(&self.parent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,7 +139,7 @@ impl fmt::Display for Directory {
|
||||||
"S {name:<10} < {parent:<10}{relative_path:<10} : {notes}",
|
"S {name:<10} < {parent:<10}{relative_path:<10} : {notes}",
|
||||||
name = self.name(),
|
name = self.name(),
|
||||||
parent = self.parent,
|
parent = self.parent,
|
||||||
relative_path = self.relative_path.display(),
|
relative_path = self.relative_path.iter().collect::<PathBuf>().display(),
|
||||||
notes = self.notes,
|
notes = self.notes,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -177,7 +183,8 @@ mod test {
|
||||||
"subdir".into(),
|
"subdir".into(),
|
||||||
"some note".to_string(),
|
"some note".to_string(),
|
||||||
local_infos,
|
local_infos,
|
||||||
);
|
)
|
||||||
|
.unwrap();
|
||||||
let mut storages = Storages::new();
|
let mut storages = Storages::new();
|
||||||
storages.add(storages::Storage::Physical(physical)).unwrap();
|
storages.add(storages::Storage::Physical(physical)).unwrap();
|
||||||
storages.add(Storage::SubDirectory(directory)).unwrap();
|
storages.add(Storage::SubDirectory(directory)).unwrap();
|
||||||
|
|
Loading…
Reference in a new issue