online storage & fix directory parent find & and so on

This commit is contained in:
qwjyh 2023-12-06 11:18:46 +09:00
parent 83233740aa
commit b54cbf00f0
5 changed files with 99 additions and 36 deletions

View file

@ -12,16 +12,13 @@ extern crate log;
extern crate dirs; extern crate dirs;
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
use byte_unit::Byte;
use clap::error::ErrorKind; use clap::error::ErrorKind;
use clap::{CommandFactory, Parser, Subcommand}; use clap::{CommandFactory, Parser, Subcommand};
use clap_verbosity_flag::Verbosity; use clap_verbosity_flag::Verbosity;
use git2::{Commit, Oid, Repository}; use git2::{Commit, Oid, Repository};
use inquire::{validator::Validation, Text}; use inquire::{validator::Validation, Text};
use serde::{Deserialize, Serialize};
use serde_yaml; use serde_yaml;
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt::format;
use std::path::PathBuf; use std::path::PathBuf;
use std::{env, io::BufReader, path::Path}; use std::{env, io::BufReader, path::Path};
use std::{ use std::{
@ -33,8 +30,8 @@ use std::{fs, io::prelude::*};
use sysinfo::{Disk, DiskExt, SystemExt}; use sysinfo::{Disk, DiskExt, SystemExt};
use crate::storages::{ use crate::storages::{
directory::Directory, get_storages, local_info, physical_drive_partition::*, write_storages, directory::Directory, get_storages, local_info, online_storage, physical_drive_partition::*,
Storage, StorageExt, StorageType, STORAGESFILE, write_storages, Storage, StorageExt, StorageType, STORAGESFILE,
}; };
use devices::{Device, DEVICESFILE, *}; use devices::{Device, DEVICESFILE, *};
@ -81,6 +78,7 @@ enum StorageCommands {
#[arg(value_enum)] #[arg(value_enum)]
storage_type: StorageType, storage_type: StorageType,
// TODO: set this require and select matching disk for physical
#[arg(short, long, value_name = "PATH")] #[arg(short, long, value_name = "PATH")]
path: Option<PathBuf>, path: Option<PathBuf>,
}, },
@ -235,6 +233,7 @@ fn main() -> Result<()> {
)?; )?;
(key_name, Storage::SubDirectory(storage)) (key_name, Storage::SubDirectory(storage))
} }
StorageType::Online => todo!(),
}; };
// add to storages // add to storages
@ -283,7 +282,7 @@ fn main() -> Result<()> {
.to_str() .to_str()
.context("Failed to convert disk name to valid string")?; .context("Failed to convert disk name to valid string")?;
// add to storages // add to storages
storage.add_alias(disk, &config_dir)?; storage.bind_device(disk, &config_dir)?;
trace!("storage: {}", storage); trace!("storage: {}", storage);
format!("{} to {}", system_name, storage.name()) format!("{} to {}", system_name, storage.name())
}; };

View file

@ -1,8 +1,9 @@
//! Manipulates storages. //! Manipulates storages.
use crate::storages::physical_drive_partition::PhysicalDrivePartition;
use crate::storages::directory::Directory;
use crate::devices; use crate::devices;
use crate::storages::directory::Directory;
use crate::storages::online_storage::OnlineStorage;
use crate::storages::physical_drive_partition::PhysicalDrivePartition;
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
use clap::ValueEnum; use clap::ValueEnum;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -15,7 +16,7 @@ pub const STORAGESFILE: &str = "storages.yml";
pub enum StorageType { pub enum StorageType {
Physical, Physical,
SubDirectory, SubDirectory,
// Online, Online,
} }
/// All storage types. /// All storage types.
@ -23,24 +24,20 @@ pub enum StorageType {
pub enum Storage { pub enum Storage {
PhysicalStorage(PhysicalDrivePartition), PhysicalStorage(PhysicalDrivePartition),
SubDirectory(Directory), SubDirectory(Directory),
// /// Online storage provided by others. Online(OnlineStorage),
// OnlineStorage {
// name: String,
// provider: String,
// capacity: u8,
// },
} }
impl Storage { impl Storage {
/// Add or update alias of `disk` for current device. /// Add or update alias of `disk` for current device.
pub fn add_alias( pub fn bind_device(
&mut self, &mut self,
disk: &sysinfo::Disk, disk: &sysinfo::Disk,
config_dir: &std::path::PathBuf, config_dir: &std::path::PathBuf,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
match self { match self {
Self::PhysicalStorage(s) => s.add_alias(disk, config_dir), Self::PhysicalStorage(s) => s.bind_device(disk, config_dir),
Self::SubDirectory(_) => Err(anyhow!("SubDirectory doesn't have system alias.")), Self::SubDirectory(_) => Err(anyhow!("SubDirectory doesn't have system alias.")),
Self::Online(_) => todo!(),
} }
} }
} }
@ -50,16 +47,15 @@ impl StorageExt for Storage {
match self { match self {
Self::PhysicalStorage(s) => s.name(), Self::PhysicalStorage(s) => s.name(),
Self::SubDirectory(s) => s.name(), Self::SubDirectory(s) => s.name(),
Self::Online(s) => s.name(),
} }
} }
fn has_alias( fn has_alias(&self, device: &devices::Device) -> bool {
&self,
device: &devices::Device,
) -> bool {
match self { match self {
Self::PhysicalStorage(s) => s.has_alias(&device), Self::PhysicalStorage(s) => s.has_alias(&device),
Self::SubDirectory(s) => s.has_alias(&device), Self::SubDirectory(s) => s.has_alias(&device),
Self::Online(s) => s.has_alias(&device),
} }
} }
@ -71,6 +67,7 @@ impl StorageExt for Storage {
match self { match self {
Self::PhysicalStorage(s) => s.mount_path(&device, &storages), Self::PhysicalStorage(s) => s.mount_path(&device, &storages),
Self::SubDirectory(s) => s.mount_path(&device, &storages), Self::SubDirectory(s) => s.mount_path(&device, &storages),
Self::Online(s) => s.mount_path(&device, &storages),
} }
} }
} }
@ -80,6 +77,7 @@ impl fmt::Display for Storage {
match self { match self {
Self::PhysicalStorage(s) => s.fmt(f), Self::PhysicalStorage(s) => s.fmt(f),
Self::SubDirectory(s) => s.fmt(f), Self::SubDirectory(s) => s.fmt(f),
Self::Online(s) => s.fmt(f),
} }
} }
} }
@ -88,6 +86,7 @@ impl fmt::Display for Storage {
pub trait StorageExt { pub trait StorageExt {
fn name(&self) -> &String; fn name(&self) -> &String;
fn has_alias(&self, device: &devices::Device) -> bool; fn has_alias(&self, device: &devices::Device) -> bool;
/// Get mount path of `self` on `device`.
fn mount_path( fn mount_path(
&self, &self,
device: &devices::Device, device: &devices::Device,
@ -97,6 +96,7 @@ pub trait StorageExt {
pub mod directory; pub mod directory;
pub mod local_info; pub mod local_info;
pub mod online_storage;
pub mod physical_drive_partition; pub mod physical_drive_partition;
/// Get `Vec<Storage>` from devices.yml([DEVICESFILE]). /// Get `Vec<Storage>` from devices.yml([DEVICESFILE]).

View file

@ -2,13 +2,7 @@
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{ use std::{collections::HashMap, fmt, path};
collections::HashMap,
fmt::{self, write},
hash::Hash,
path,
rc::Rc,
};
use crate::devices; use crate::devices;
@ -31,7 +25,7 @@ impl Directory {
/// - `notes`: supplimental notes. /// - `notes`: supplimental notes.
fn new( fn new(
name: String, name: String,
parent: String, // todo implement serialize parent: String,
relative_path: path::PathBuf, relative_path: path::PathBuf,
notes: String, notes: String,
local_info: HashMap<String, LocalInfo>, local_info: HashMap<String, LocalInfo>,
@ -58,7 +52,11 @@ impl Directory {
.filter_map(|(k, v)| { .filter_map(|(k, v)| {
let diff = pathdiff::diff_paths(&path, v.mount_path(&device, &storages).unwrap())?; let diff = pathdiff::diff_paths(&path, v.mount_path(&device, &storages).unwrap())?;
trace!("Pathdiff: {:?}", diff); trace!("Pathdiff: {:?}", diff);
Some((k, diff)) if diff.components().any(|c| c == path::Component::ParentDir) {
None
} else {
Some((k, diff))
}
}) })
.min_by_key(|(_k, v)| { .min_by_key(|(_k, v)| {
let diff_paths: Vec<path::Component<'_>> = v.components().collect(); let diff_paths: Vec<path::Component<'_>> = v.components().collect();
@ -106,6 +104,16 @@ impl Directory {
let parent_mount_path = parent.mount_path(&device, &storages)?; let parent_mount_path = parent.mount_path(&device, &storages)?;
Ok(parent_mount_path.join(self.relative_path.clone())) 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(())
}
} }
impl StorageExt for Directory { impl StorageExt for Directory {

View file

@ -0,0 +1,61 @@
//! Online storage which is not a children of any physical drive.
use anyhow::Context;
use byte_unit::Byte;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt;
use std::path;
use crate::devices;
use super::local_info::LocalInfo;
use super::StorageExt;
#[derive(Serialize, Deserialize, Debug)]
pub struct OnlineStorage {
name: String,
provider: String,
capacity: u8,
local_info: HashMap<String, LocalInfo>,
}
impl OnlineStorage {
fn new(name: String, provider: String, capacity: u8, path: path::PathBuf, device: &devices::Device) -> OnlineStorage {
todo!()
}
}
impl StorageExt for OnlineStorage {
fn name(&self) -> &String {
&self.name
}
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, super::Storage>,
) -> anyhow::Result<std::path::PathBuf> {
Ok(self
.local_info
.get(&device.name())
.context(format!("LocalInfo for storage: {} not found", &self.name()))?
.mount_path())
}
}
impl fmt::Display for OnlineStorage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"O {name:<10} {size} {provider:<10}",
name = self.name(),
size = Byte::from_bytes(self.capacity.into()).get_appropriate_unit(true),
provider = self.provider,
)
}
}

View file

@ -28,11 +28,6 @@ pub struct PhysicalDrivePartition {
local_info: HashMap<String, LocalInfo>, local_info: HashMap<String, LocalInfo>,
} }
pub struct PhysicalDrivePartitionLocal {
alias: String,
mount_path: path::PathBuf,
}
impl PhysicalDrivePartition { impl PhysicalDrivePartition {
/// Try to get Physical drive info from sysinfo. /// Try to get Physical drive info from sysinfo.
pub fn try_from_sysinfo_disk( pub fn try_from_sysinfo_disk(
@ -60,7 +55,7 @@ impl PhysicalDrivePartition {
}) })
} }
pub fn add_alias( pub fn bind_device(
&mut self, &mut self,
disk: &sysinfo::Disk, disk: &sysinfo::Disk,
config_dir: &std::path::PathBuf, config_dir: &std::path::PathBuf,