update storage list and some refactor

This commit is contained in:
qwjyh 2024-03-03 06:11:25 +09:00
parent ff72228821
commit 24f34da588
10 changed files with 257 additions and 51 deletions

1
Cargo.lock generated
View file

@ -1125,4 +1125,5 @@ dependencies = [
"serde", "serde",
"serde_yaml", "serde_yaml",
"sysinfo", "sysinfo",
"unicode-width",
] ]

View file

@ -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"

View file

@ -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 {

View file

@ -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

View file

@ -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,

View file

@ -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,

View file

@ -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")
);
}
}

View file

@ -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"));
}

View file

@ -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,

View file

@ -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,