From 5f81eccd2d3f4c43c0a98c551c32455f207a3e96 Mon Sep 17 00:00:00 2001 From: qwjyh Date: Fri, 8 Dec 2023 03:18:31 +0900 Subject: [PATCH] add for online, refactored bind --- README.md | 3 + src/main.rs | 75 +++++++++++++++++++----- src/storages.rs | 55 +++++++++++------ src/storages/directory.rs | 29 +++++---- src/storages/local_info.rs | 4 ++ src/storages/online_storage.rs | 42 +++++++++++-- src/storages/physical_drive_partition.rs | 24 ++++++-- 7 files changed, 175 insertions(+), 57 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..07b1df8 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# TODO: +- [ ] reorganize cmd option for storage + - [ ] use subcommand diff --git a/src/main.rs b/src/main.rs index 447ff1e..89296e2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,6 +31,7 @@ use std::{fs, io::prelude::*}; use sysinfo::{Disk, DiskExt, SystemExt}; use crate::inquire_filepath_completer::FilePathCompleter; +use crate::storages::online_storage::OnlineStorage; use crate::storages::{ directory::Directory, get_storages, local_info, online_storage, physical_drive_partition::*, write_storages, Storage, StorageExt, StorageType, STORAGESFILE, @@ -89,9 +90,18 @@ enum StorageCommands { }, /// List all storages. List {}, - /// Add new device-specific name to existing storage. + /// Make `storage` available for the current device. /// For physical disk, the name is taken from system info automatically. - Bind { storage: String }, + Bind { + /// Name of the storage. + storage: String, + /// Device specific alias for the storage. + #[arg(short, long)] + alias: String, + /// Mount point on this device. + #[arg(short, long)] + path: path::PathBuf, + }, } mod devices; @@ -296,7 +306,40 @@ fn main() -> Result<()> { )?; (key_name, Storage::SubDirectory(storage)) } - StorageType::Online => todo!(), + StorageType::Online => { + let path = path.unwrap_or_else(|| { + let mut cmd = Cli::command(); + cmd.error( + ErrorKind::MissingRequiredArgument, + " is required with sub-directory", + ) + .exit(); + }); + let mut name = String::new(); + loop { + name = Text::new("Name for the storage:") + .with_validator(min_length!(0, "At least 1 character")) + .prompt() + .context("Failed to get Name")?; + if storages.iter().all(|(k, _v)| k != &name) { + break; + } + println!("The name {} is already used.", name); + } + let provider = Text::new("Provider:").prompt().context("Failed to get provider")?; + let capacity: u64 = CustomType::::new("Capacity (byte):") + .with_error_message("Please type number.") + .prompt() + .context("Failed to get capacity.")?; + let alias = Text::new("Alias:").prompt().context("Failed to get provider")?; + let storage = OnlineStorage::new( + name.clone(), provider, capacity, alias, path, &device, + ); + ( + name, + Storage::Online(storage), + ) + } }; // add to storages @@ -328,26 +371,26 @@ fn main() -> Result<()> { } StorageCommands::Bind { storage: storage_name, + alias: new_alias, + path: mount_point, } => { + let device = get_device(&config_dir)?; // get storages let mut storages: HashMap = get_storages(&config_dir)?; let commit_comment = { // find matching storage - let storage = storages + let storage = &mut storages .get_mut(&storage_name) .context(format!("No storage has name {}", storage_name))?; - // get disk from sysinfo - let mut sysinfo = sysinfo::System::new_all(); - sysinfo.refresh_disks(); - let disk = select_sysinfo_disk(&sysinfo)?; - let system_name = disk - .name() - .to_str() - .context("Failed to convert disk name to valid string")?; - // add to storages - storage.bind_device(disk, &config_dir)?; - trace!("storage: {}", storage); - format!("{} to {}", system_name, storage.name()) + let old_alias = storage + .local_info(&device) + .context(format!("Failed to get LocalInfo for {}", storage.name()))? + .alias() + .clone(); + // TODO: get mount path for directory automatically? + storage.bound_on_device(new_alias, mount_point, &device)?; + // trace!("storage: {}", &storage); + format!("{} to {}", old_alias, storage.name()) }; trace!("bound new system name to the storage"); trace!("storages: {:#?}", storages); diff --git a/src/storages.rs b/src/storages.rs index 6cb7a4d..912e632 100644 --- a/src/storages.rs +++ b/src/storages.rs @@ -27,20 +27,7 @@ pub enum Storage { Online(OnlineStorage), } -impl Storage { - /// Add or update alias of `disk` for current device. - pub fn bind_device( - &mut self, - disk: &sysinfo::Disk, - config_dir: &std::path::PathBuf, - ) -> anyhow::Result<()> { - match self { - Self::PhysicalStorage(s) => s.bind_device(disk, config_dir), - Self::SubDirectory(_) => Err(anyhow!("SubDirectory doesn't have system alias.")), - Self::Online(_) => todo!(), - } - } -} +impl Storage {} impl StorageExt for Storage { fn name(&self) -> &String { @@ -51,11 +38,11 @@ impl StorageExt for Storage { } } - fn has_alias(&self, device: &devices::Device) -> bool { + fn local_info(&self, device: &devices::Device) -> Option<&local_info::LocalInfo> { match self { - Self::PhysicalStorage(s) => s.has_alias(&device), - Self::SubDirectory(s) => s.has_alias(&device), - Self::Online(s) => s.has_alias(&device), + Self::PhysicalStorage(s) => s.local_info(device), + Self::SubDirectory(s) => s.local_info(device), + Self::Online(s) => s.local_info(device), } } @@ -70,6 +57,19 @@ impl StorageExt for Storage { Self::Online(s) => s.mount_path(&device, &storages), } } + + fn bound_on_device( + &mut self, + alias: String, + mount_point: path::PathBuf, + device: &devices::Device, + ) -> Result<()> { + match self { + Storage::PhysicalStorage(s) => s.bound_on_device(alias, mount_point, device), + Storage::SubDirectory(s) => s.bound_on_device(alias, mount_point, device), + Storage::Online(s) => s.bound_on_device(alias, mount_point, device), + } + } } impl fmt::Display for Storage { @@ -85,13 +85,30 @@ impl fmt::Display for Storage { /// Trait to manipulate all `Storage`s (Enums). pub trait StorageExt { fn name(&self) -> &String; - fn has_alias(&self, device: &devices::Device) -> bool; + + /// Return `true` if `self` has local info on the `device`. + /// Used to check if the storage is bound on the `device`. + fn has_alias(&self, device: &devices::Device) -> bool { + self.local_info(device).is_some() + } + + /// Get local info of `device`. + fn local_info(&self, device: &devices::Device) -> Option<&local_info::LocalInfo>; + /// Get mount path of `self` on `device`. fn mount_path( &self, device: &devices::Device, storages: &HashMap, ) -> Result; + + /// Add local info of `device` to `self`. + fn bound_on_device( + &mut self, + alias: String, + mount_point: path::PathBuf, + device: &devices::Device, + ) -> Result<()>; } pub mod directory; diff --git a/src/storages/directory.rs b/src/storages/directory.rs index 5367ea9..c77a480 100644 --- a/src/storages/directory.rs +++ b/src/storages/directory.rs @@ -104,16 +104,6 @@ impl Directory { 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) -> 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 { @@ -121,8 +111,8 @@ impl StorageExt for Directory { &self.name } - fn has_alias(&self, device: &devices::Device) -> bool { - self.local_info.get(&device.name()).is_some() + fn local_info(&self, device: &devices::Device) -> Option<&LocalInfo> { + self.local_info.get(&device.name()) } fn mount_path( @@ -132,6 +122,21 @@ impl StorageExt for Directory { ) -> Result { Ok(self.mount_path(device, storages)?) } + + /// This method doesn't use `mount_path`. + fn bound_on_device( + &mut self, + alias: String, + mount_point: path::PathBuf, + device: &devices::Device, + ) -> Result<()> { + let new_local_info = LocalInfo::new(alias, mount_point); + 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 fmt::Display for Directory { diff --git a/src/storages/local_info.rs b/src/storages/local_info.rs index 1369ba8..4e36a33 100644 --- a/src/storages/local_info.rs +++ b/src/storages/local_info.rs @@ -18,6 +18,10 @@ impl LocalInfo { LocalInfo { alias, mount_path } } + pub fn alias(&self) -> String { + self.alias.clone() // ? + } + pub fn mount_path(&self) -> path::PathBuf { self.mount_path.clone() } diff --git a/src/storages/online_storage.rs b/src/storages/online_storage.rs index 06e9abe..77b16da 100644 --- a/src/storages/online_storage.rs +++ b/src/storages/online_storage.rs @@ -1,6 +1,6 @@ //! Online storage which is not a children of any physical drive. -use anyhow::Context; +use anyhow::{Context, Result}; use byte_unit::Byte; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -9,6 +9,7 @@ use std::path; use crate::devices; +use super::local_info; use super::local_info::LocalInfo; use super::StorageExt; @@ -16,13 +17,26 @@ use super::StorageExt; pub struct OnlineStorage { name: String, provider: String, - capacity: u8, + capacity: u64, local_info: HashMap, } impl OnlineStorage { - fn new(name: String, provider: String, capacity: u8, path: path::PathBuf, device: &devices::Device) -> OnlineStorage { - todo!() + pub fn new( + name: String, + provider: String, + capacity: u64, + alias: String, + path: path::PathBuf, + device: &devices::Device, + ) -> OnlineStorage { + let local_info = local_info::LocalInfo::new(alias, path); + OnlineStorage { + name, + provider, + capacity, + local_info: HashMap::from([(device.name(), local_info)]), + } } } @@ -31,8 +45,8 @@ impl StorageExt for OnlineStorage { &self.name } - fn has_alias(&self, device: &devices::Device) -> bool { - self.local_info.get(&device.name()).is_some() + fn local_info(&self, device: &devices::Device) -> Option<&LocalInfo> { + self.local_info.get(&device.name()) } fn mount_path( @@ -46,6 +60,22 @@ impl StorageExt for OnlineStorage { .context(format!("LocalInfo for storage: {} not found", &self.name()))? .mount_path()) } + + fn bound_on_device( + &mut self, + alias: String, + mount_point: path::PathBuf, + device: &devices::Device, + ) -> Result<()> { + match self + .local_info + .insert(device.name(), LocalInfo::new(alias, mount_point)) + { + Some(old) => info!("Value replaced. Old value: {:?}", old), + None => info!("New value inserted."), + }; + Ok(()) + } } impl fmt::Display for OnlineStorage { diff --git a/src/storages/physical_drive_partition.rs b/src/storages/physical_drive_partition.rs index bd89fce..48eeb76 100644 --- a/src/storages/physical_drive_partition.rs +++ b/src/storages/physical_drive_partition.rs @@ -36,7 +36,7 @@ impl PhysicalDrivePartition { fs: String, is_removable: bool, local_info: LocalInfo, - device: &Device + device: &Device, ) -> PhysicalDrivePartition { PhysicalDrivePartition { name, @@ -101,8 +101,8 @@ impl StorageExt for PhysicalDrivePartition { &self.name } - fn has_alias(&self, device: &devices::Device) -> bool { - self.local_info.get(&device.name()).is_some() + fn local_info(&self, device: &devices::Device) -> Option<&local_info::LocalInfo> { + self.local_info.get(&device.name()) } fn mount_path( @@ -116,6 +116,22 @@ impl StorageExt for PhysicalDrivePartition { .context(format!("LocalInfo for storage: {} not found", &self.name()))? .mount_path()) } + + fn bound_on_device( + &mut self, + alias: String, + mount_point: path::PathBuf, + device: &devices::Device, + ) -> Result<()> { + match self + .local_info + .insert(device.name(), LocalInfo::new(alias, mount_point)) + { + Some(old) => info!("Value replaced. Old value: {:?}", old), + None => info!("New value inserted."), + }; + Ok(()) + } } impl fmt::Display for PhysicalDrivePartition { @@ -141,7 +157,7 @@ pub fn select_physical_storage( ) -> Result<(String, PhysicalDrivePartition)> { trace!("select_physical_storage"); // get disk info fron sysinfo - let mut sys_disks = + let sys_disks = sysinfo::System::new_with_specifics(sysinfo::RefreshKind::new().with_disks_list()); trace!("refresh"); // sys_disks.refresh_disks_list();