mirror of
https://github.com/qwjyh/xdbm
synced 2025-07-07 07:09:19 +09:00
new: adding sub-directory
This commit is contained in:
parent
7a4c1e5325
commit
abcb01897f
6 changed files with 255 additions and 53 deletions
|
@ -5,13 +5,14 @@ use serde::{Deserialize, Serialize};
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
fmt::{self, write},
|
||||
hash::Hash,
|
||||
path,
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
use crate::devices;
|
||||
|
||||
use super::{Storage, StorageExt};
|
||||
use super::{local_info::LocalInfo, Storage, StorageExt};
|
||||
|
||||
/// Subdirectory of other [Storage]s.
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
@ -20,6 +21,7 @@ pub struct Directory {
|
|||
parent: String,
|
||||
relative_path: path::PathBuf,
|
||||
notes: String,
|
||||
local_info: HashMap<String, LocalInfo>,
|
||||
}
|
||||
|
||||
impl Directory {
|
||||
|
@ -27,40 +29,83 @@ impl Directory {
|
|||
/// - `parent`: where the directory locates.
|
||||
/// - `relative_path`: path from root of the parent storage.
|
||||
/// - `notes`: supplimental notes.
|
||||
pub fn new(
|
||||
fn new(
|
||||
name: String,
|
||||
parent: String, // todo implement serialize
|
||||
relative_path: path::PathBuf,
|
||||
notes: String,
|
||||
local_info: HashMap<String, LocalInfo>,
|
||||
) -> Directory {
|
||||
Directory {
|
||||
name,
|
||||
parent,
|
||||
relative_path,
|
||||
notes,
|
||||
local_info,
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
Some((k, diff))
|
||||
})
|
||||
.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,
|
||||
)
|
||||
}
|
||||
|
||||
/// Get parent `&Storage` of directory.
|
||||
fn parent<'a>(&'a self, storages: &'a HashMap<String, Storage>) -> Result<&Storage> {
|
||||
let parent = &self.parent;
|
||||
storages.get(&self.parent.clone()).context(format!(
|
||||
storages.get(parent).context(format!(
|
||||
"No parent {} exists for directory {}",
|
||||
parent,
|
||||
self.name()
|
||||
))
|
||||
}
|
||||
|
||||
// /// 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()))
|
||||
// }
|
||||
/// 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()))
|
||||
}
|
||||
}
|
||||
|
||||
impl StorageExt for Directory {
|
||||
|
@ -68,9 +113,17 @@ impl StorageExt for Directory {
|
|||
&self.name
|
||||
}
|
||||
|
||||
// fn mount_path(&self, &device: &devices::Device, &storages: &HashMap<String, Storage>) -> Result<&path::PathBuf> {
|
||||
// Ok(&self.mount_path(&device, &storages)?)
|
||||
// }
|
||||
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)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Directory {
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::path;
|
||||
|
||||
/// Store local (device-specific) information
|
||||
///
|
||||
/// - `alias`: name in device
|
||||
/// - `mount_path`: mount path on the device
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct LocalInfo {
|
||||
alias: String,
|
||||
|
@ -12,7 +16,7 @@ impl LocalInfo {
|
|||
LocalInfo { alias, mount_path }
|
||||
}
|
||||
|
||||
pub fn mount_path(&self) -> &path::PathBuf {
|
||||
&self.mount_path
|
||||
pub fn mount_path(&self) -> path::PathBuf {
|
||||
self.mount_path.clone()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ impl PhysicalDrivePartition {
|
|||
let fs = disk.file_system();
|
||||
trace!("fs: {:?}", fs);
|
||||
let fs = std::str::from_utf8(fs)?;
|
||||
let local_info = LocalInfo::new(alias, disk.mount_point().to_path_buf());
|
||||
let local_info = LocalInfo::new(alias, disk.mount_point().to_path_buf().canonicalize()?);
|
||||
Ok(PhysicalDrivePartition {
|
||||
name: name,
|
||||
kind: format!("{:?}", disk.kind()),
|
||||
|
@ -87,13 +87,17 @@ impl StorageExt for PhysicalDrivePartition {
|
|||
&self.name
|
||||
}
|
||||
|
||||
// fn mount_path(&self, &device: &devices::Device, &storages: &HashMap<String, Storage>) -> Result<&path::PathBuf> {
|
||||
// Ok(&self
|
||||
// .local_info
|
||||
// .get(&device.name())
|
||||
// .context(format!("LocalInfo for storage: {} not found", &self.name()))?
|
||||
// .mount_path())
|
||||
// }
|
||||
fn has_alias(&self, device: &devices::Device) -> bool {
|
||||
self.local_info.get(&device.name()).is_some()
|
||||
}
|
||||
|
||||
fn mount_path(&self, device: &devices::Device, _: &HashMap<String, Storage>) -> Result<path::PathBuf> {
|
||||
Ok(self
|
||||
.local_info
|
||||
.get(&device.name())
|
||||
.context(format!("LocalInfo for storage: {} not found", &self.name()))?
|
||||
.mount_path())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PhysicalDrivePartition {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue