xdbm/src/storages/directory.rs

149 lines
4.4 KiB
Rust
Raw Normal View History

2023-09-01 10:37:30 +09:00
//! Manipulate subdirectories of other storages, including directories.
2023-12-04 21:34:24 +09:00
use anyhow::{anyhow, Context, Result};
2023-09-01 10:37:30 +09:00
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, fmt, path};
2023-12-04 21:34:24 +09:00
use crate::devices;
2023-09-01 10:37:30 +09:00
2023-12-05 03:24:49 +09:00
use super::{local_info::LocalInfo, Storage, StorageExt};
2023-09-01 10:37:30 +09:00
/// Subdirectory of other [Storage]s.
#[derive(Serialize, Deserialize, Debug)]
pub struct Directory {
name: String,
2023-12-04 21:34:24 +09:00
parent: String,
2023-09-01 10:37:30 +09:00
relative_path: path::PathBuf,
notes: String,
2023-12-05 03:24:49 +09:00
local_info: HashMap<String, LocalInfo>,
2023-09-01 10:37:30 +09:00
}
impl Directory {
/// - `name`: id
/// - `parent`: where the directory locates.
/// - `relative_path`: path from root of the parent storage.
/// - `notes`: supplimental notes.
2023-12-05 03:24:49 +09:00
fn new(
2023-09-01 10:37:30 +09:00
name: String,
parent: String,
2023-09-01 10:37:30 +09:00
relative_path: path::PathBuf,
notes: String,
2023-12-05 03:24:49 +09:00
local_info: HashMap<String, LocalInfo>,
2023-09-01 10:37:30 +09:00
) -> Directory {
2023-12-04 21:34:24 +09:00
Directory {
name,
parent,
relative_path,
notes,
2023-12-05 03:24:49 +09:00
local_info,
2023-12-04 21:34:24 +09:00
}
}
2023-12-05 03:24:49 +09:00
pub fn try_from_device_path(
name: String,
path: path::PathBuf,
notes: String,
device: &devices::Device,
storages: &HashMap<String, Storage>,
) -> Result<Directory> {
let (parent_name, diff_path) = storages
.iter()
.filter(|(_k, v)| v.has_alias(&device))
.filter_map(|(k, v)| {
let diff = pathdiff::diff_paths(&path, v.mount_path(&device, &storages).unwrap())?;
trace!("Pathdiff: {:?}", diff);
if diff.components().any(|c| c == path::Component::ParentDir) {
None
} else {
Some((k, diff))
}
2023-12-05 03:24:49 +09:00
})
.min_by_key(|(_k, v)| {
let diff_paths: Vec<path::Component<'_>> = v.components().collect();
diff_paths.len()
})
.context(format!("Failed to compare diff of paths"))?;
trace!("Selected parent: {}", parent_name);
let local_info = LocalInfo::new("".to_string(), path);
Ok(Directory::new(
name,
parent_name.clone(),
diff_path,
notes,
HashMap::from([(device.name(), local_info)]),
))
}
pub fn update_note(self, notes: String) -> Directory {
Directory::new(
self.name,
self.parent,
self.relative_path,
notes,
self.local_info,
)
}
2023-12-04 21:34:24 +09:00
/// Get parent `&Storage` of directory.
fn parent<'a>(&'a self, storages: &'a HashMap<String, Storage>) -> Result<&Storage> {
let parent = &self.parent;
2023-12-05 03:24:49 +09:00
storages.get(parent).context(format!(
2023-12-04 21:34:24 +09:00
"No parent {} exists for directory {}",
parent,
self.name()
))
2023-09-01 10:37:30 +09:00
}
2023-12-04 21:34:24 +09:00
2023-12-05 03:24:49 +09:00
/// Resolve mount path of directory with current device.
fn mount_path(
&self,
device: &devices::Device,
storages: &HashMap<String, Storage>,
) -> Result<path::PathBuf> {
let parent = self.parent(&storages)?;
let parent_mount_path = parent.mount_path(&device, &storages)?;
Ok(parent_mount_path.join(self.relative_path.clone()))
}
fn bind_device(&mut self, alias: String, device: &devices::Device, storages: &HashMap<String, Storage>) -> Result<()> {
let mount_path = self.mount_path(&device, &storages)?;
let new_local_info = LocalInfo::new(alias, mount_path);
match self.local_info.insert(device.name(), new_local_info) {
Some(v) => println!("Value updated. old val is: {:?}", v),
None => println!("inserted new val"),
};
Ok(())
}
2023-09-01 10:37:30 +09:00
}
impl StorageExt for Directory {
fn name(&self) -> &String {
&self.name
}
2023-12-04 21:34:24 +09:00
2023-12-05 03:24:49 +09:00
fn has_alias(&self, device: &devices::Device) -> bool {
self.local_info.get(&device.name()).is_some()
}
fn mount_path(
&self,
device: &devices::Device,
storages: &HashMap<String, Storage>,
) -> Result<path::PathBuf> {
Ok(self.mount_path(device, storages)?)
}
2023-09-01 10:37:30 +09:00
}
impl fmt::Display for Directory {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"S {name:<10} < {parent:<10}{relative_path:<10} : {notes}",
name = self.name(),
parent = self.parent,
relative_path = self.relative_path.display(),
notes = self.notes,
)
}
2023-12-04 21:34:24 +09:00
}