mirror of
https://github.com/qwjyh/xdbm
synced 2024-11-22 14:50:12 +09:00
update storage list and some refactor
This commit is contained in:
parent
ff72228821
commit
24f34da588
10 changed files with 257 additions and 51 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1125,4 +1125,5 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
"sysinfo",
|
"sysinfo",
|
||||||
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
|
@ -19,3 +19,4 @@ serde_yaml = "0.9"
|
||||||
byte-unit = "4.0.19"
|
byte-unit = "4.0.19"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
pathdiff = "0.2.1"
|
pathdiff = "0.2.1"
|
||||||
|
unicode-width = "0.1.11"
|
||||||
|
|
|
@ -57,7 +57,11 @@ pub(crate) enum StorageCommands {
|
||||||
path: Option<PathBuf>,
|
path: Option<PathBuf>,
|
||||||
},
|
},
|
||||||
/// List all storages.
|
/// List all storages.
|
||||||
List {},
|
List {
|
||||||
|
/// Show note on the storages.
|
||||||
|
#[arg(short, long)]
|
||||||
|
long: bool,
|
||||||
|
},
|
||||||
/// Make `storage` available for the current device.
|
/// 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 {
|
Bind {
|
||||||
|
|
|
@ -2,22 +2,24 @@
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
path::{Path, PathBuf},
|
io::{self, Write},
|
||||||
|
path::{Path, PathBuf}, string,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
|
use byte_unit::Byte;
|
||||||
use clap::{error::ErrorKind, CommandFactory};
|
use clap::{error::ErrorKind, CommandFactory};
|
||||||
use git2::Repository;
|
use git2::Repository;
|
||||||
use inquire::{min_length, Confirm, CustomType, Select, Text};
|
use inquire::{min_length, Confirm, CustomType, Select, Text};
|
||||||
|
use unicode_width::{self, UnicodeWidthStr};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
add_and_commit, ask_unique_name,
|
add_and_commit, ask_unique_name,
|
||||||
cmd_args::Cli,
|
cmd_args::Cli,
|
||||||
get_device,
|
devices::{self, Device},
|
||||||
inquire_filepath_completer::FilePathCompleter,
|
inquire_filepath_completer::FilePathCompleter,
|
||||||
storages::{
|
storages::{
|
||||||
self, directory, get_storages, local_info, physical_drive_partition, Storage, StorageExt,
|
self, directory, local_info, physical_drive_partition, Storage, StorageExt, StorageType,
|
||||||
StorageType,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,10 +32,10 @@ pub(crate) fn cmd_storage_add(
|
||||||
trace!("Storage Add {:?}, {:?}", storage_type, path);
|
trace!("Storage Add {:?}, {:?}", storage_type, path);
|
||||||
// Get storages
|
// Get storages
|
||||||
// let mut storages: Vec<Storage> = get_storages(&config_dir)?;
|
// let mut storages: Vec<Storage> = get_storages(&config_dir)?;
|
||||||
let mut storages: HashMap<String, Storage> = get_storages(&config_dir)?;
|
let mut storages: HashMap<String, Storage> = storages::get_storages(&config_dir)?;
|
||||||
trace!("found storages: {:?}", storages);
|
trace!("found storages: {:?}", storages);
|
||||||
|
|
||||||
let device = get_device(&config_dir)?;
|
let device = devices::get_device(&config_dir)?;
|
||||||
let (key, storage) = match storage_type {
|
let (key, storage) = match storage_type {
|
||||||
StorageType::Physical => {
|
StorageType::Physical => {
|
||||||
let use_sysinfo = {
|
let use_sysinfo = {
|
||||||
|
@ -110,6 +112,7 @@ pub(crate) fn cmd_storage_add(
|
||||||
}
|
}
|
||||||
let path = path.unwrap_or_else(|| {
|
let path = path.unwrap_or_else(|| {
|
||||||
let mut cmd = Cli::command();
|
let mut cmd = Cli::command();
|
||||||
|
// TODO: weired def of cmd argument
|
||||||
cmd.error(
|
cmd.error(
|
||||||
ErrorKind::MissingRequiredArgument,
|
ErrorKind::MissingRequiredArgument,
|
||||||
"<PATH> is required with sub-directory",
|
"<PATH> is required with sub-directory",
|
||||||
|
@ -193,15 +196,88 @@ pub(crate) fn cmd_storage_add(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn cmd_storage_list(config_dir: &PathBuf) -> Result<()> {
|
pub(crate) fn cmd_storage_list(config_dir: &PathBuf, with_note: bool) -> Result<()> {
|
||||||
// Get storages
|
// Get storages
|
||||||
let storages: HashMap<String, Storage> = get_storages(&config_dir)?;
|
let storages: HashMap<String, Storage> = storages::get_storages(&config_dir)?;
|
||||||
trace!("found storages: {:?}", storages);
|
trace!("found storages: {:?}", storages);
|
||||||
let device = get_device(&config_dir)?;
|
let device = devices::get_device(&config_dir)?;
|
||||||
for (k, storage) in &storages {
|
let mut stdout = io::BufWriter::new(io::stdout());
|
||||||
println!("{}: {}", k, storage);
|
write_storages_list(&mut stdout, &storages, &device, with_note)?;
|
||||||
println!(" {}", storage.mount_path(&device, &storages)?.display());
|
stdout.flush()?;
|
||||||
// println!("{}: {}", storage.shorttypename(), storage.name()); // TODO
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_storages_list(
|
||||||
|
mut writer: impl io::Write,
|
||||||
|
storages: &HashMap<String, Storage>,
|
||||||
|
device: &Device,
|
||||||
|
long_display: bool,
|
||||||
|
) -> Result<()> {
|
||||||
|
let name_width = storages
|
||||||
|
.iter()
|
||||||
|
.map(|(_k, v)| v.name().width())
|
||||||
|
.max()
|
||||||
|
.unwrap();
|
||||||
|
trace!("name widths: {}", name_width);
|
||||||
|
for (_k, storage) in storages {
|
||||||
|
let size_str = match storage.capacity() {
|
||||||
|
Some(b) => Byte::from_bytes(b.into())
|
||||||
|
.get_appropriate_unit(true)
|
||||||
|
.format(0)
|
||||||
|
.to_string(),
|
||||||
|
None => "".to_string(),
|
||||||
|
};
|
||||||
|
let isremovable = if let Storage::PhysicalStorage(s) = storage {
|
||||||
|
if s.is_removable() {
|
||||||
|
"+"
|
||||||
|
} else {
|
||||||
|
"-"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
" "
|
||||||
|
};
|
||||||
|
let path = storage.mount_path(&device, &storages).map_or_else(
|
||||||
|
|e| {
|
||||||
|
info!("Not found: {}", e);
|
||||||
|
"".to_string()
|
||||||
|
},
|
||||||
|
|v| v.display().to_string(),
|
||||||
|
);
|
||||||
|
let parent_name = if let Storage::SubDirectory(s) = storage {
|
||||||
|
s.parent(&storages)
|
||||||
|
.context(format!("Failed to get parent of storage {}", s))?
|
||||||
|
.name()
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
};
|
||||||
|
writeln!(
|
||||||
|
writer,
|
||||||
|
"{stype}{isremovable}: {name:<name_width$} {size:>8} {parent:<name_width$} {path}",
|
||||||
|
stype = storage.shorttypename(),
|
||||||
|
isremovable = isremovable,
|
||||||
|
name = storage.name(),
|
||||||
|
size = size_str,
|
||||||
|
parent = parent_name,
|
||||||
|
path = path,
|
||||||
|
)?;
|
||||||
|
if long_display {
|
||||||
|
let note = match storage {
|
||||||
|
Storage::PhysicalStorage(s) => {
|
||||||
|
s.kind()
|
||||||
|
},
|
||||||
|
Storage::SubDirectory(s) => {
|
||||||
|
&s.notes
|
||||||
|
},
|
||||||
|
Storage::Online(s) => {
|
||||||
|
&s.provider
|
||||||
|
},
|
||||||
|
};
|
||||||
|
writeln!(
|
||||||
|
writer,
|
||||||
|
" {}",
|
||||||
|
note
|
||||||
|
)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -213,9 +289,9 @@ pub(crate) fn cmd_storage_bind(
|
||||||
repo: Repository,
|
repo: Repository,
|
||||||
config_dir: &PathBuf,
|
config_dir: &PathBuf,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let device = get_device(&config_dir)?;
|
let device = devices::get_device(&config_dir)?;
|
||||||
// get storages
|
// get storages
|
||||||
let mut storages: HashMap<String, Storage> = get_storages(&config_dir)?;
|
let mut storages: HashMap<String, Storage> = storages::get_storages(&config_dir)?;
|
||||||
let commit_comment = {
|
let commit_comment = {
|
||||||
// find matching storage
|
// find matching storage
|
||||||
let storage = &mut storages
|
let storage = &mut storages
|
||||||
|
|
|
@ -13,7 +13,6 @@ extern crate log;
|
||||||
extern crate dirs;
|
extern crate dirs;
|
||||||
|
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use clap::error::ErrorKind;
|
|
||||||
use clap::{CommandFactory, Parser};
|
use clap::{CommandFactory, Parser};
|
||||||
use git2::{Commit, Oid, Repository};
|
use git2::{Commit, Oid, Repository};
|
||||||
use inquire::{min_length, Confirm, CustomType, Select};
|
use inquire::{min_length, Confirm, CustomType, Select};
|
||||||
|
@ -24,7 +23,6 @@ use std::path::Path;
|
||||||
use std::path::{self, PathBuf};
|
use std::path::{self, PathBuf};
|
||||||
|
|
||||||
use crate::cmd_args::{Cli, Commands, StorageCommands};
|
use crate::cmd_args::{Cli, Commands, StorageCommands};
|
||||||
use crate::cmd_storage;
|
|
||||||
use crate::storages::online_storage;
|
use crate::storages::online_storage;
|
||||||
use crate::storages::{
|
use crate::storages::{
|
||||||
directory, get_storages, local_info, physical_drive_partition, write_storages, Storage,
|
directory, get_storages, local_info, physical_drive_partition, write_storages, Storage,
|
||||||
|
@ -64,7 +62,7 @@ fn main() -> Result<()> {
|
||||||
StorageCommands::Add { storage_type, path } => {
|
StorageCommands::Add { storage_type, path } => {
|
||||||
cmd_storage::cmd_storage_add(storage_type, path, repo, &config_dir)?
|
cmd_storage::cmd_storage_add(storage_type, path, repo, &config_dir)?
|
||||||
}
|
}
|
||||||
StorageCommands::List {} => cmd_storage::cmd_storage_list(&config_dir)?,
|
StorageCommands::List { long } => cmd_storage::cmd_storage_list(&config_dir, long)?,
|
||||||
StorageCommands::Bind {
|
StorageCommands::Bind {
|
||||||
storage: storage_name,
|
storage: storage_name,
|
||||||
alias: new_alias,
|
alias: new_alias,
|
||||||
|
|
|
@ -7,7 +7,7 @@ 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};
|
||||||
use std::{collections::HashMap, ffi, fmt, fs, io, path};
|
use std::{collections::HashMap, ffi, fmt, fs, io, path, u64};
|
||||||
|
|
||||||
/// YAML file to store known storages..
|
/// YAML file to store known storages..
|
||||||
pub const STORAGESFILE: &str = "storages.yml";
|
pub const STORAGESFILE: &str = "storages.yml";
|
||||||
|
@ -88,6 +88,14 @@ impl StorageExt for Storage {
|
||||||
Storage::Online(s) => s.bound_on_device(alias, mount_point, device),
|
Storage::Online(s) => s.bound_on_device(alias, mount_point, device),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn capacity(&self) -> Option<u64> {
|
||||||
|
match self {
|
||||||
|
Storage::PhysicalStorage(s) => s.capacity(),
|
||||||
|
Storage::SubDirectory(s) => s.capacity(),
|
||||||
|
Storage::Online(s) => s.capacity(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Storage {
|
impl fmt::Display for Storage {
|
||||||
|
@ -104,6 +112,10 @@ impl fmt::Display for Storage {
|
||||||
pub trait StorageExt {
|
pub trait StorageExt {
|
||||||
fn name(&self) -> &String;
|
fn name(&self) -> &String;
|
||||||
|
|
||||||
|
/// Capacity in bytes.
|
||||||
|
/// Since [Directory] has no capacity information, it has `None`.
|
||||||
|
fn capacity(&self) -> Option<u64>;
|
||||||
|
|
||||||
/// Return `true` if `self` has local info on the `device`.
|
/// Return `true` if `self` has local info on the `device`.
|
||||||
/// Used to check if the storage is bound on the `device`.
|
/// Used to check if the storage is bound on the `device`.
|
||||||
fn has_alias(&self, device: &devices::Device) -> bool {
|
fn has_alias(&self, device: &devices::Device) -> bool {
|
||||||
|
@ -114,6 +126,7 @@ pub trait StorageExt {
|
||||||
fn local_info(&self, device: &devices::Device) -> Option<&local_info::LocalInfo>;
|
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`.
|
||||||
|
/// `storages` is a `HashMap` with key of storage name and value of the storage.
|
||||||
fn mount_path(
|
fn mount_path(
|
||||||
&self,
|
&self,
|
||||||
device: &devices::Device,
|
device: &devices::Device,
|
||||||
|
|
|
@ -14,8 +14,8 @@ pub struct Directory {
|
||||||
name: String,
|
name: String,
|
||||||
parent: String,
|
parent: String,
|
||||||
relative_path: path::PathBuf,
|
relative_path: path::PathBuf,
|
||||||
notes: String,
|
pub notes: String,
|
||||||
local_info: HashMap<String, LocalInfo>,
|
local_infos: HashMap<String, LocalInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Directory {
|
impl Directory {
|
||||||
|
@ -28,14 +28,14 @@ impl Directory {
|
||||||
parent: String,
|
parent: String,
|
||||||
relative_path: path::PathBuf,
|
relative_path: path::PathBuf,
|
||||||
notes: String,
|
notes: String,
|
||||||
local_info: HashMap<String, LocalInfo>,
|
local_infos: HashMap<String, LocalInfo>,
|
||||||
) -> Directory {
|
) -> Directory {
|
||||||
Directory {
|
Directory {
|
||||||
name,
|
name,
|
||||||
parent,
|
parent,
|
||||||
relative_path,
|
relative_path,
|
||||||
notes,
|
notes,
|
||||||
local_info,
|
local_infos,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,12 +80,12 @@ impl Directory {
|
||||||
self.parent,
|
self.parent,
|
||||||
self.relative_path,
|
self.relative_path,
|
||||||
notes,
|
notes,
|
||||||
self.local_info,
|
self.local_infos,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get parent `&Storage` of directory.
|
/// Get parent `&Storage` of directory.
|
||||||
fn parent<'a>(&'a self, storages: &'a HashMap<String, Storage>) -> Result<&Storage> {
|
pub fn parent<'a>(&'a self, storages: &'a HashMap<String, Storage>) -> Result<&Storage> {
|
||||||
let parent = &self.parent;
|
let parent = &self.parent;
|
||||||
storages.get(parent).context(format!(
|
storages.get(parent).context(format!(
|
||||||
"No parent {} exists for directory {}",
|
"No parent {} exists for directory {}",
|
||||||
|
@ -111,8 +111,12 @@ impl StorageExt for Directory {
|
||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn capacity(&self) -> Option<u64> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn local_info(&self, device: &devices::Device) -> Option<&LocalInfo> {
|
fn local_info(&self, device: &devices::Device) -> Option<&LocalInfo> {
|
||||||
self.local_info.get(&device.name())
|
self.local_infos.get(&device.name())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mount_path(
|
fn mount_path(
|
||||||
|
@ -131,7 +135,7 @@ impl StorageExt for Directory {
|
||||||
device: &devices::Device,
|
device: &devices::Device,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let new_local_info = LocalInfo::new(alias, mount_point);
|
let new_local_info = LocalInfo::new(alias, mount_point);
|
||||||
match self.local_info.insert(device.name(), new_local_info) {
|
match self.local_infos.insert(device.name(), new_local_info) {
|
||||||
Some(v) => println!("Value updated. old val is: {:?}", v),
|
Some(v) => println!("Value updated. old val is: {:?}", v),
|
||||||
None => println!("inserted new val"),
|
None => println!("inserted new val"),
|
||||||
};
|
};
|
||||||
|
@ -151,3 +155,64 @@ impl fmt::Display for Directory {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
devices::Device,
|
||||||
|
storages::{
|
||||||
|
self, local_info::LocalInfo, physical_drive_partition::PhysicalDrivePartition, Storage,
|
||||||
|
StorageExt,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::Directory;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn name() {
|
||||||
|
let local_info_phys =
|
||||||
|
LocalInfo::new("phys_alias".to_string(), PathBuf::from("/mnt/sample"));
|
||||||
|
let local_info_dir =
|
||||||
|
LocalInfo::new("dir_alias".to_string(), PathBuf::from("/mnt/sample/subdir"));
|
||||||
|
let device = Device::new("test_device".to_string());
|
||||||
|
let mut local_infos = HashMap::new();
|
||||||
|
local_infos.insert(device.name(), local_info_dir);
|
||||||
|
let physical = PhysicalDrivePartition::new(
|
||||||
|
"parent".to_string(),
|
||||||
|
"SSD".to_string(),
|
||||||
|
1_000_000_000,
|
||||||
|
"btrfs".to_string(),
|
||||||
|
false,
|
||||||
|
local_info_phys,
|
||||||
|
&device,
|
||||||
|
);
|
||||||
|
let directory = Directory::new(
|
||||||
|
"test_name".to_owned(),
|
||||||
|
"parent".to_string(),
|
||||||
|
"subdir".into(),
|
||||||
|
"some note".to_string(),
|
||||||
|
local_infos,
|
||||||
|
);
|
||||||
|
let mut storages: HashMap<String, Storage> = HashMap::new();
|
||||||
|
storages.insert(
|
||||||
|
physical.name().to_string(),
|
||||||
|
Storage::PhysicalStorage(physical),
|
||||||
|
);
|
||||||
|
storages.insert(
|
||||||
|
directory.name().to_string(),
|
||||||
|
Storage::SubDirectory(directory),
|
||||||
|
);
|
||||||
|
// assert_eq!(directory.name(), "test_name");
|
||||||
|
assert_eq!(storages.get("test_name").unwrap().name(), "test_name");
|
||||||
|
assert_eq!(
|
||||||
|
storages
|
||||||
|
.get("test_name")
|
||||||
|
.unwrap()
|
||||||
|
.mount_path(&device, &storages)
|
||||||
|
.unwrap(),
|
||||||
|
PathBuf::from("/mnt/sample/subdir")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! Device specific common data for storages.
|
//! Device specific common data for storages.
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::path;
|
use std::path::{self, PathBuf};
|
||||||
|
|
||||||
/// Store local (device-specific) information
|
/// Store local (device-specific) information
|
||||||
///
|
///
|
||||||
|
@ -26,3 +26,10 @@ impl LocalInfo {
|
||||||
self.mount_path.clone()
|
self.mount_path.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn localinfo() {
|
||||||
|
let localinfo = LocalInfo::new("alias".to_string(), PathBuf::from("/mnt/sample"));
|
||||||
|
assert_eq!(localinfo.alias(), "alias".to_string());
|
||||||
|
assert_eq!(localinfo.mount_path(), PathBuf::from("/mnt/sample"));
|
||||||
|
}
|
||||||
|
|
|
@ -9,16 +9,17 @@ use std::path;
|
||||||
|
|
||||||
use crate::devices;
|
use crate::devices;
|
||||||
|
|
||||||
use super::local_info;
|
use super::{
|
||||||
use super::local_info::LocalInfo;
|
local_info::{self, LocalInfo},
|
||||||
use super::StorageExt;
|
StorageExt,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct OnlineStorage {
|
pub struct OnlineStorage {
|
||||||
name: String,
|
name: String,
|
||||||
provider: String,
|
pub provider: String,
|
||||||
capacity: u64,
|
capacity: u64,
|
||||||
local_info: HashMap<String, LocalInfo>,
|
local_infos: HashMap<String, LocalInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OnlineStorage {
|
impl OnlineStorage {
|
||||||
|
@ -35,7 +36,7 @@ impl OnlineStorage {
|
||||||
name,
|
name,
|
||||||
provider,
|
provider,
|
||||||
capacity,
|
capacity,
|
||||||
local_info: HashMap::from([(device.name(), local_info)]),
|
local_infos: HashMap::from([(device.name(), local_info)]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,17 +46,21 @@ impl StorageExt for OnlineStorage {
|
||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn capacity(&self) -> Option<u64> {
|
||||||
|
Some(self.capacity)
|
||||||
|
}
|
||||||
|
|
||||||
fn local_info(&self, device: &devices::Device) -> Option<&LocalInfo> {
|
fn local_info(&self, device: &devices::Device) -> Option<&LocalInfo> {
|
||||||
self.local_info.get(&device.name())
|
self.local_infos.get(&device.name())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mount_path(
|
fn mount_path(
|
||||||
&self,
|
&self,
|
||||||
device: &devices::Device,
|
device: &devices::Device,
|
||||||
_storages: &HashMap<String, super::Storage>,
|
_storages: &HashMap<String, super::Storage>,
|
||||||
) -> anyhow::Result<std::path::PathBuf> {
|
) -> Result<std::path::PathBuf> {
|
||||||
Ok(self
|
Ok(self
|
||||||
.local_info
|
.local_infos
|
||||||
.get(&device.name())
|
.get(&device.name())
|
||||||
.context(format!("LocalInfo for storage: {} not found", &self.name()))?
|
.context(format!("LocalInfo for storage: {} not found", &self.name()))?
|
||||||
.mount_path())
|
.mount_path())
|
||||||
|
@ -68,7 +73,7 @@ impl StorageExt for OnlineStorage {
|
||||||
device: &devices::Device,
|
device: &devices::Device,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
match self
|
match self
|
||||||
.local_info
|
.local_infos
|
||||||
.insert(device.name(), LocalInfo::new(alias, mount_point))
|
.insert(device.name(), LocalInfo::new(alias, mount_point))
|
||||||
{
|
{
|
||||||
Some(old) => info!("Value replaced. Old value: {:?}", old),
|
Some(old) => info!("Value replaced. Old value: {:?}", old),
|
||||||
|
@ -82,7 +87,7 @@ impl fmt::Display for OnlineStorage {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"O {name:<10} {size} {provider:<10}",
|
"O {name:<10} {size:<10} {provider:<10}",
|
||||||
name = self.name(),
|
name = self.name(),
|
||||||
size = Byte::from_bytes(self.capacity.into()).get_appropriate_unit(true),
|
size = Byte::from_bytes(self.capacity.into()).get_appropriate_unit(true),
|
||||||
provider = self.provider,
|
provider = self.provider,
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
//! Manipulate partition of physical drive (both removable and unremovable).
|
//! Manipulate partition of physical drive (both removable and unremovable).
|
||||||
|
|
||||||
use crate::devices;
|
use crate::devices;
|
||||||
|
use crate::devices::Device;
|
||||||
use crate::storages::{Storage, StorageExt};
|
use crate::storages::{Storage, StorageExt};
|
||||||
use crate::{devices::Device, get_device};
|
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use byte_unit::Byte;
|
use byte_unit::Byte;
|
||||||
use inquire::Text;
|
use inquire::Text;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::path;
|
use std::path::{self, PathBuf};
|
||||||
use std::{
|
use std::{
|
||||||
collections::{hash_map::RandomState, HashMap},
|
collections::{hash_map::RandomState, HashMap},
|
||||||
fmt,
|
fmt,
|
||||||
|
@ -25,7 +25,7 @@ pub struct PhysicalDrivePartition {
|
||||||
fs: String,
|
fs: String,
|
||||||
is_removable: bool,
|
is_removable: bool,
|
||||||
// system_names: HashMap<String, String>,
|
// system_names: HashMap<String, String>,
|
||||||
local_info: HashMap<String, LocalInfo>,
|
local_infos: HashMap<String, LocalInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PhysicalDrivePartition {
|
impl PhysicalDrivePartition {
|
||||||
|
@ -44,7 +44,7 @@ impl PhysicalDrivePartition {
|
||||||
capacity,
|
capacity,
|
||||||
fs,
|
fs,
|
||||||
is_removable,
|
is_removable,
|
||||||
local_info: HashMap::from([(device.name(), local_info)]),
|
local_infos: HashMap::from([(device.name(), local_info)]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ impl PhysicalDrivePartition {
|
||||||
fs: fs.to_string(),
|
fs: fs.to_string(),
|
||||||
is_removable: disk.is_removable(),
|
is_removable: disk.is_removable(),
|
||||||
// system_names: HashMap::from([(device.name(), alias)]),
|
// system_names: HashMap::from([(device.name(), alias)]),
|
||||||
local_info: HashMap::from([(device.name(), local_info)]),
|
local_infos: HashMap::from([(device.name(), local_info)]),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,13 +79,13 @@ impl PhysicalDrivePartition {
|
||||||
disk: &sysinfo::Disk,
|
disk: &sysinfo::Disk,
|
||||||
config_dir: &std::path::PathBuf,
|
config_dir: &std::path::PathBuf,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let device = get_device(&config_dir)?;
|
let device = devices::get_device(&config_dir)?;
|
||||||
let alias = match disk.name().to_str() {
|
let alias = match disk.name().to_str() {
|
||||||
Some(s) => s.to_string(),
|
Some(s) => s.to_string(),
|
||||||
None => return Err(anyhow!("Failed to convert storage name to valid str.")),
|
None => return Err(anyhow!("Failed to convert storage name to valid str.")),
|
||||||
};
|
};
|
||||||
let new_local_info = LocalInfo::new(alias, disk.mount_point().to_path_buf());
|
let new_local_info = LocalInfo::new(alias, disk.mount_point().to_path_buf());
|
||||||
let aliases = &mut self.local_info;
|
let aliases = &mut self.local_infos;
|
||||||
trace!("aliases: {:?}", aliases);
|
trace!("aliases: {:?}", aliases);
|
||||||
match aliases.insert(device.name(), new_local_info) {
|
match aliases.insert(device.name(), new_local_info) {
|
||||||
Some(v) => println!("Value updated. old val is: {:?}", v),
|
Some(v) => println!("Value updated. old val is: {:?}", v),
|
||||||
|
@ -94,6 +94,38 @@ impl PhysicalDrivePartition {
|
||||||
trace!("aliases: {:?}", aliases);
|
trace!("aliases: {:?}", aliases);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_removable(&self) -> bool {
|
||||||
|
self.is_removable
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kind(&self) -> &String {
|
||||||
|
&self.kind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crate::{devices::Device, storages::{local_info::LocalInfo, StorageExt}};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use super::PhysicalDrivePartition;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_new() {
|
||||||
|
let localinfo = LocalInfo::new("alias".to_string(), PathBuf::from("/mnt/sample"));
|
||||||
|
let storage = PhysicalDrivePartition::new(
|
||||||
|
"name".to_string(),
|
||||||
|
"SSD".to_string(),
|
||||||
|
100,
|
||||||
|
"ext_4".to_string(),
|
||||||
|
true,
|
||||||
|
localinfo,
|
||||||
|
&Device::new("test_device".to_string()),
|
||||||
|
);
|
||||||
|
assert_eq!(storage.name(), "name");
|
||||||
|
assert_eq!(storage.capacity(), Some(100));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StorageExt for PhysicalDrivePartition {
|
impl StorageExt for PhysicalDrivePartition {
|
||||||
|
@ -101,8 +133,12 @@ impl StorageExt for PhysicalDrivePartition {
|
||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn capacity(&self) -> Option<u64> {
|
||||||
|
Some(self.capacity)
|
||||||
|
}
|
||||||
|
|
||||||
fn local_info(&self, device: &devices::Device) -> Option<&local_info::LocalInfo> {
|
fn local_info(&self, device: &devices::Device) -> Option<&local_info::LocalInfo> {
|
||||||
self.local_info.get(&device.name())
|
self.local_infos.get(&device.name())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mount_path(
|
fn mount_path(
|
||||||
|
@ -111,7 +147,7 @@ impl StorageExt for PhysicalDrivePartition {
|
||||||
_: &HashMap<String, Storage>,
|
_: &HashMap<String, Storage>,
|
||||||
) -> Result<path::PathBuf> {
|
) -> Result<path::PathBuf> {
|
||||||
Ok(self
|
Ok(self
|
||||||
.local_info
|
.local_infos
|
||||||
.get(&device.name())
|
.get(&device.name())
|
||||||
.context(format!("LocalInfo for storage: {} not found", &self.name()))?
|
.context(format!("LocalInfo for storage: {} not found", &self.name()))?
|
||||||
.mount_path())
|
.mount_path())
|
||||||
|
@ -124,7 +160,7 @@ impl StorageExt for PhysicalDrivePartition {
|
||||||
device: &devices::Device,
|
device: &devices::Device,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
match self
|
match self
|
||||||
.local_info
|
.local_infos
|
||||||
.insert(device.name(), LocalInfo::new(alias, mount_point))
|
.insert(device.name(), LocalInfo::new(alias, mount_point))
|
||||||
{
|
{
|
||||||
Some(old) => info!("Value replaced. Old value: {:?}", old),
|
Some(old) => info!("Value replaced. Old value: {:?}", old),
|
||||||
|
@ -139,7 +175,7 @@ impl fmt::Display for PhysicalDrivePartition {
|
||||||
let removable_indicator = if self.is_removable { "+" } else { "-" };
|
let removable_indicator = if self.is_removable { "+" } else { "-" };
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"P {name:<10} {size} {removable:<1} {kind:<6} {fs:<5}",
|
"P {name:<10} {size:<10} {removable:<1} {kind:<6} {fs:<5}",
|
||||||
name = self.name(),
|
name = self.name(),
|
||||||
size = Byte::from_bytes(self.capacity.into()).get_appropriate_unit(true),
|
size = Byte::from_bytes(self.capacity.into()).get_appropriate_unit(true),
|
||||||
removable = removable_indicator,
|
removable = removable_indicator,
|
||||||
|
|
Loading…
Reference in a new issue