add for online, refactored bind

This commit is contained in:
qwjyh 2023-12-08 03:18:31 +09:00
parent 017e34d392
commit 5f81eccd2d
7 changed files with 175 additions and 57 deletions

3
README.md Normal file
View file

@ -0,0 +1,3 @@
# TODO:
- [ ] reorganize cmd option for storage
- [ ] use subcommand

View file

@ -31,6 +31,7 @@ use std::{fs, io::prelude::*};
use sysinfo::{Disk, DiskExt, SystemExt}; use sysinfo::{Disk, DiskExt, SystemExt};
use crate::inquire_filepath_completer::FilePathCompleter; use crate::inquire_filepath_completer::FilePathCompleter;
use crate::storages::online_storage::OnlineStorage;
use crate::storages::{ use crate::storages::{
directory::Directory, get_storages, local_info, online_storage, physical_drive_partition::*, directory::Directory, get_storages, local_info, online_storage, physical_drive_partition::*,
write_storages, Storage, StorageExt, StorageType, STORAGESFILE, write_storages, Storage, StorageExt, StorageType, STORAGESFILE,
@ -89,9 +90,18 @@ enum StorageCommands {
}, },
/// List all storages. /// List all storages.
List {}, 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. /// 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; mod devices;
@ -296,7 +306,40 @@ fn main() -> Result<()> {
)?; )?;
(key_name, Storage::SubDirectory(storage)) (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,
"<PATH> 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::<u64>::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 // add to storages
@ -328,26 +371,26 @@ fn main() -> Result<()> {
} }
StorageCommands::Bind { StorageCommands::Bind {
storage: storage_name, storage: storage_name,
alias: new_alias,
path: mount_point,
} => { } => {
let device = get_device(&config_dir)?;
// get storages // get storages
let mut storages: HashMap<String, Storage> = get_storages(&config_dir)?; let mut storages: HashMap<String, Storage> = get_storages(&config_dir)?;
let commit_comment = { let commit_comment = {
// find matching storage // find matching storage
let storage = storages let storage = &mut storages
.get_mut(&storage_name) .get_mut(&storage_name)
.context(format!("No storage has name {}", storage_name))?; .context(format!("No storage has name {}", storage_name))?;
// get disk from sysinfo let old_alias = storage
let mut sysinfo = sysinfo::System::new_all(); .local_info(&device)
sysinfo.refresh_disks(); .context(format!("Failed to get LocalInfo for {}", storage.name()))?
let disk = select_sysinfo_disk(&sysinfo)?; .alias()
let system_name = disk .clone();
.name() // TODO: get mount path for directory automatically?
.to_str() storage.bound_on_device(new_alias, mount_point, &device)?;
.context("Failed to convert disk name to valid string")?; // trace!("storage: {}", &storage);
// add to storages format!("{} to {}", old_alias, storage.name())
storage.bind_device(disk, &config_dir)?;
trace!("storage: {}", storage);
format!("{} to {}", system_name, storage.name())
}; };
trace!("bound new system name to the storage"); trace!("bound new system name to the storage");
trace!("storages: {:#?}", storages); trace!("storages: {:#?}", storages);

View file

@ -27,20 +27,7 @@ pub enum Storage {
Online(OnlineStorage), Online(OnlineStorage),
} }
impl Storage { 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 StorageExt for Storage { impl StorageExt for Storage {
fn name(&self) -> &String { 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 { match self {
Self::PhysicalStorage(s) => s.has_alias(&device), Self::PhysicalStorage(s) => s.local_info(device),
Self::SubDirectory(s) => s.has_alias(&device), Self::SubDirectory(s) => s.local_info(device),
Self::Online(s) => s.has_alias(&device), Self::Online(s) => s.local_info(device),
} }
} }
@ -70,6 +57,19 @@ impl StorageExt for Storage {
Self::Online(s) => s.mount_path(&device, &storages), 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 { impl fmt::Display for Storage {
@ -85,13 +85,30 @@ impl fmt::Display for Storage {
/// Trait to manipulate all `Storage`s (Enums). /// Trait to manipulate all `Storage`s (Enums).
pub trait StorageExt { pub trait StorageExt {
fn name(&self) -> &String; 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`. /// Get mount path of `self` on `device`.
fn mount_path( fn mount_path(
&self, &self,
device: &devices::Device, device: &devices::Device,
storages: &HashMap<String, Storage>, storages: &HashMap<String, Storage>,
) -> Result<path::PathBuf>; ) -> Result<path::PathBuf>;
/// 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; pub mod directory;

View file

@ -104,16 +104,6 @@ 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 {
@ -121,8 +111,8 @@ impl StorageExt for Directory {
&self.name &self.name
} }
fn has_alias(&self, device: &devices::Device) -> bool { fn local_info(&self, device: &devices::Device) -> Option<&LocalInfo> {
self.local_info.get(&device.name()).is_some() self.local_info.get(&device.name())
} }
fn mount_path( fn mount_path(
@ -132,6 +122,21 @@ impl StorageExt for Directory {
) -> Result<path::PathBuf> { ) -> Result<path::PathBuf> {
Ok(self.mount_path(device, storages)?) 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 { impl fmt::Display for Directory {

View file

@ -18,6 +18,10 @@ impl LocalInfo {
LocalInfo { alias, mount_path } LocalInfo { alias, mount_path }
} }
pub fn alias(&self) -> String {
self.alias.clone() // ?
}
pub fn mount_path(&self) -> path::PathBuf { pub fn mount_path(&self) -> path::PathBuf {
self.mount_path.clone() self.mount_path.clone()
} }

View file

@ -1,6 +1,6 @@
//! Online storage which is not a children of any physical drive. //! Online storage which is not a children of any physical drive.
use anyhow::Context; use anyhow::{Context, Result};
use byte_unit::Byte; use byte_unit::Byte;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
@ -9,6 +9,7 @@ use std::path;
use crate::devices; use crate::devices;
use super::local_info;
use super::local_info::LocalInfo; use super::local_info::LocalInfo;
use super::StorageExt; use super::StorageExt;
@ -16,13 +17,26 @@ use super::StorageExt;
pub struct OnlineStorage { pub struct OnlineStorage {
name: String, name: String,
provider: String, provider: String,
capacity: u8, capacity: u64,
local_info: HashMap<String, LocalInfo>, local_info: HashMap<String, LocalInfo>,
} }
impl OnlineStorage { impl OnlineStorage {
fn new(name: String, provider: String, capacity: u8, path: path::PathBuf, device: &devices::Device) -> OnlineStorage { pub fn new(
todo!() 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 &self.name
} }
fn has_alias(&self, device: &devices::Device) -> bool { fn local_info(&self, device: &devices::Device) -> Option<&LocalInfo> {
self.local_info.get(&device.name()).is_some() self.local_info.get(&device.name())
} }
fn mount_path( fn mount_path(
@ -46,6 +60,22 @@ impl StorageExt for OnlineStorage {
.context(format!("LocalInfo for storage: {} not found", &self.name()))? .context(format!("LocalInfo for storage: {} not found", &self.name()))?
.mount_path()) .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 { impl fmt::Display for OnlineStorage {

View file

@ -36,7 +36,7 @@ impl PhysicalDrivePartition {
fs: String, fs: String,
is_removable: bool, is_removable: bool,
local_info: LocalInfo, local_info: LocalInfo,
device: &Device device: &Device,
) -> PhysicalDrivePartition { ) -> PhysicalDrivePartition {
PhysicalDrivePartition { PhysicalDrivePartition {
name, name,
@ -101,8 +101,8 @@ impl StorageExt for PhysicalDrivePartition {
&self.name &self.name
} }
fn has_alias(&self, device: &devices::Device) -> bool { fn local_info(&self, device: &devices::Device) -> Option<&local_info::LocalInfo> {
self.local_info.get(&device.name()).is_some() self.local_info.get(&device.name())
} }
fn mount_path( fn mount_path(
@ -116,6 +116,22 @@ impl StorageExt for PhysicalDrivePartition {
.context(format!("LocalInfo for storage: {} not found", &self.name()))? .context(format!("LocalInfo for storage: {} not found", &self.name()))?
.mount_path()) .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 { impl fmt::Display for PhysicalDrivePartition {
@ -141,7 +157,7 @@ pub fn select_physical_storage(
) -> Result<(String, PhysicalDrivePartition)> { ) -> Result<(String, PhysicalDrivePartition)> {
trace!("select_physical_storage"); trace!("select_physical_storage");
// get disk info fron sysinfo // get disk info fron sysinfo
let mut sys_disks = let sys_disks =
sysinfo::System::new_with_specifics(sysinfo::RefreshKind::new().with_disks_list()); sysinfo::System::new_with_specifics(sysinfo::RefreshKind::new().with_disks_list());
trace!("refresh"); trace!("refresh");
// sys_disks.refresh_disks_list(); // sys_disks.refresh_disks_list();