mirror of
https://github.com/qwjyh/xdbm
synced 2024-11-22 14:50:12 +09:00
refactoring: moved storage related functions to crate storage
This commit is contained in:
parent
78b2d956a7
commit
33e1a9aba7
3 changed files with 124 additions and 109 deletions
122
src/main.rs
122
src/main.rs
|
@ -30,8 +30,11 @@ use std::{
|
||||||
use std::{fs, io::prelude::*};
|
use std::{fs, io::prelude::*};
|
||||||
use sysinfo::{Disk, DiskExt, SystemExt};
|
use sysinfo::{Disk, DiskExt, SystemExt};
|
||||||
|
|
||||||
|
use crate::storages::{
|
||||||
|
get_storages, physical_drive_partition::*, write_storages, Storage, StorageExt, StorageType,
|
||||||
|
STORAGESFILE,
|
||||||
|
};
|
||||||
use devices::{Device, DEVICESFILE};
|
use devices::{Device, DEVICESFILE};
|
||||||
use storages::{physical_drive_partition::*, Storage, StorageExt, StorageType, STORAGESFILE};
|
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[command(author, version, about, long_about = None)]
|
#[command(author, version, about, long_about = None)]
|
||||||
|
@ -235,7 +238,10 @@ fn main() -> Result<()> {
|
||||||
let mut sysinfo = sysinfo::System::new_all();
|
let mut sysinfo = sysinfo::System::new_all();
|
||||||
sysinfo.refresh_disks();
|
sysinfo.refresh_disks();
|
||||||
let disk = select_sysinfo_disk(&sysinfo)?;
|
let disk = select_sysinfo_disk(&sysinfo)?;
|
||||||
let system_name = disk.name().to_str().context("Failed to convert disk name to valid string")?;
|
let system_name = disk
|
||||||
|
.name()
|
||||||
|
.to_str()
|
||||||
|
.context("Failed to convert disk name to valid string")?;
|
||||||
// add to storages
|
// add to storages
|
||||||
storage.add_alias(disk, &config_dir)?;
|
storage.add_alias(disk, &config_dir)?;
|
||||||
trace!("storage: {}", storage);
|
trace!("storage: {}", storage);
|
||||||
|
@ -249,9 +255,15 @@ fn main() -> Result<()> {
|
||||||
add_and_commit(
|
add_and_commit(
|
||||||
&repo,
|
&repo,
|
||||||
&Path::new(STORAGESFILE),
|
&Path::new(STORAGESFILE),
|
||||||
&format!("Bound new storage name to physical drive ({})", commit_comment),
|
&format!(
|
||||||
|
"Bound new storage name to physical drive ({})",
|
||||||
|
commit_comment
|
||||||
|
),
|
||||||
)?;
|
)?;
|
||||||
println!("Bound new storage name to physical drive ({})", commit_comment);
|
println!(
|
||||||
|
"Bound new storage name to physical drive ({})",
|
||||||
|
commit_comment
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -344,108 +356,6 @@ fn write_devices(config_dir: &Path, devices: Vec<Device>) -> Result<()> {
|
||||||
serde_yaml::to_writer(writer, &devices).map_err(|e| anyhow!(e))
|
serde_yaml::to_writer(writer, &devices).map_err(|e| anyhow!(e))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Interactively select physical storage from available disks in sysinfo.
|
|
||||||
fn select_physical_storage(
|
|
||||||
device: Device,
|
|
||||||
storages: &Vec<Storage>,
|
|
||||||
) -> Result<PhysicalDrivePartition> {
|
|
||||||
trace!("select_physical_storage");
|
|
||||||
// get disk info fron sysinfo
|
|
||||||
let mut sys_disks = sysinfo::System::new_all();
|
|
||||||
sys_disks.refresh_disks();
|
|
||||||
trace!("Available disks");
|
|
||||||
for disk in sys_disks.disks() {
|
|
||||||
trace!("{:?}", disk)
|
|
||||||
}
|
|
||||||
let disk = select_sysinfo_disk(&sys_disks)?;
|
|
||||||
// name the disk
|
|
||||||
let mut disk_name = String::new();
|
|
||||||
trace!("{}", disk_name);
|
|
||||||
loop {
|
|
||||||
disk_name = Text::new("Name for the disk:").prompt()?;
|
|
||||||
if storages.iter().all(|s| s.name() != &disk_name) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
println!("The name {} is already used.", disk_name);
|
|
||||||
}
|
|
||||||
trace!("selected name: {}", disk_name);
|
|
||||||
PhysicalDrivePartition::try_from_sysinfo_disk(&disk, disk_name, device)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn select_sysinfo_disk(sysinfo: &sysinfo::System) -> Result<&Disk> {
|
|
||||||
let available_disks = sysinfo
|
|
||||||
.disks()
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(i, disk)| {
|
|
||||||
let name = match disk.name().to_str() {
|
|
||||||
Some(s) => s,
|
|
||||||
None => "",
|
|
||||||
};
|
|
||||||
let fs: &str = std::str::from_utf8(disk.file_system()).unwrap_or("unknown");
|
|
||||||
let kind = format!("{:?}", disk.kind());
|
|
||||||
let mount_path = disk.mount_point();
|
|
||||||
let total_space = Byte::from_bytes(disk.total_space().into())
|
|
||||||
.get_appropriate_unit(true)
|
|
||||||
.to_string();
|
|
||||||
format!(
|
|
||||||
"{}: {} {} ({}, {}) {}",
|
|
||||||
i,
|
|
||||||
name,
|
|
||||||
total_space,
|
|
||||||
fs,
|
|
||||||
kind,
|
|
||||||
mount_path.display()
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
// select from list
|
|
||||||
let disk = inquire::Select::new("Select drive:", available_disks).prompt()?;
|
|
||||||
let disk_num: usize = disk.split(':').next().unwrap().parse().unwrap();
|
|
||||||
trace!("disk_num: {}", disk_num);
|
|
||||||
let disk = sysinfo
|
|
||||||
.disks()
|
|
||||||
.iter()
|
|
||||||
.nth(disk_num)
|
|
||||||
.context("no disk matched with selected one.")?;
|
|
||||||
trace!("selected disk: {:?}", disk);
|
|
||||||
Ok(disk)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get `Vec<Storage>` from devices.yml([DEVICESFILE]).
|
|
||||||
/// If [DEVICESFILE] isn't found, return empty vec.
|
|
||||||
fn get_storages(config_dir: &Path) -> Result<Vec<Storage>> {
|
|
||||||
if let Some(storages_file) = fs::read_dir(&config_dir)?
|
|
||||||
.filter(|f| {
|
|
||||||
f.as_ref().map_or_else(
|
|
||||||
|_e| false,
|
|
||||||
|f| {
|
|
||||||
let storagesfile: OsString = STORAGESFILE.into();
|
|
||||||
f.path().file_name() == Some(&storagesfile)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.next()
|
|
||||||
{
|
|
||||||
trace!("{} found: {:?}", STORAGESFILE, storages_file);
|
|
||||||
let f = File::open(config_dir.join(STORAGESFILE))?;
|
|
||||||
let reader = BufReader::new(f);
|
|
||||||
let yaml: Vec<Storage> =
|
|
||||||
serde_yaml::from_reader(reader).context("Failed to read devices.yml")?;
|
|
||||||
Ok(yaml)
|
|
||||||
} else {
|
|
||||||
trace!("No {} found", STORAGESFILE);
|
|
||||||
Ok(vec![])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write `storages` to yaml file in `config_dir`.
|
|
||||||
fn write_storages(config_dir: &Path, storages: Vec<Storage>) -> Result<()> {
|
|
||||||
let f = File::create(config_dir.join(STORAGESFILE))?;
|
|
||||||
let writer = BufWriter::new(f);
|
|
||||||
serde_yaml::to_writer(writer, &storages).map_err(|e| anyhow!(e))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_last_commit(repo: &Repository) -> Result<Option<Commit>, git2::Error> {
|
fn find_last_commit(repo: &Repository) -> Result<Option<Commit>, git2::Error> {
|
||||||
if repo.is_empty()? {
|
if repo.is_empty()? {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
//! Manipulates storages.
|
//! Manipulates storages.
|
||||||
|
|
||||||
|
use anyhow::{anyhow, Context, Result};
|
||||||
use clap::ValueEnum;
|
use clap::ValueEnum;
|
||||||
use physical_drive_partition::PhysicalDrivePartition;
|
use physical_drive_partition::PhysicalDrivePartition;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::{ffi, fmt, fs, path::Path, io};
|
||||||
|
|
||||||
/// YAML file to store known storages..
|
/// YAML file to store known storages..
|
||||||
pub const STORAGESFILE: &str = "storages.yml";
|
pub const STORAGESFILE: &str = "storages.yml";
|
||||||
|
@ -57,3 +58,37 @@ pub trait StorageExt {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod physical_drive_partition;
|
pub mod physical_drive_partition;
|
||||||
|
|
||||||
|
/// Get `Vec<Storage>` from devices.yml([DEVICESFILE]).
|
||||||
|
/// If [DEVICESFILE] isn't found, return empty vec.
|
||||||
|
pub fn get_storages(config_dir: &Path) -> Result<Vec<Storage>> {
|
||||||
|
if let Some(storages_file) = fs::read_dir(&config_dir)?
|
||||||
|
.filter(|f| {
|
||||||
|
f.as_ref().map_or_else(
|
||||||
|
|_e| false,
|
||||||
|
|f| {
|
||||||
|
let storagesfile: ffi::OsString = STORAGESFILE.into();
|
||||||
|
f.path().file_name() == Some(&storagesfile)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.next()
|
||||||
|
{
|
||||||
|
trace!("{} found: {:?}", STORAGESFILE, storages_file);
|
||||||
|
let f = fs::File::open(config_dir.join(STORAGESFILE))?;
|
||||||
|
let reader = io::BufReader::new(f);
|
||||||
|
let yaml: Vec<Storage> =
|
||||||
|
serde_yaml::from_reader(reader).context("Failed to read devices.yml")?;
|
||||||
|
Ok(yaml)
|
||||||
|
} else {
|
||||||
|
trace!("No {} found", STORAGESFILE);
|
||||||
|
Ok(vec![])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write `storages` to yaml file in `config_dir`.
|
||||||
|
pub fn write_storages(config_dir: &Path, storages: Vec<Storage>) -> Result<()> {
|
||||||
|
let f = fs::File::create(config_dir.join(STORAGESFILE))?;
|
||||||
|
let writer = io::BufWriter::new(f);
|
||||||
|
serde_yaml::to_writer(writer, &storages).map_err(|e| anyhow!(e))
|
||||||
|
}
|
|
@ -1,15 +1,16 @@
|
||||||
//! Manipulate partition of physical drive (both removable and unremovable).
|
//! Manipulate partition of physical drive (both removable and unremovable).
|
||||||
|
|
||||||
use crate::{devices::Device, get_device};
|
use crate::{devices::Device, get_device};
|
||||||
use crate::storages::StorageExt;
|
use crate::storages::{Storage, StorageExt};
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use byte_unit::Byte;
|
use byte_unit::Byte;
|
||||||
|
use inquire::Text;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
collections::{hash_map::RandomState, HashMap},
|
collections::{hash_map::RandomState, HashMap},
|
||||||
fmt,
|
fmt,
|
||||||
};
|
};
|
||||||
use sysinfo::DiskExt;
|
use sysinfo::{Disk, DiskExt, SystemExt};
|
||||||
|
|
||||||
/// Partitoin of physical (on-premises) drive.
|
/// Partitoin of physical (on-premises) drive.
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
@ -89,3 +90,72 @@ impl fmt::Display for PhysicalDrivePartition {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Interactively select physical storage from available disks in sysinfo.
|
||||||
|
pub fn select_physical_storage(
|
||||||
|
device: Device,
|
||||||
|
storages: &Vec<Storage>,
|
||||||
|
) -> Result<PhysicalDrivePartition> {
|
||||||
|
trace!("select_physical_storage");
|
||||||
|
// get disk info fron sysinfo
|
||||||
|
let mut sys_disks = sysinfo::System::new_all();
|
||||||
|
sys_disks.refresh_disks();
|
||||||
|
trace!("Available disks");
|
||||||
|
for disk in sys_disks.disks() {
|
||||||
|
trace!("{:?}", disk)
|
||||||
|
}
|
||||||
|
let disk = select_sysinfo_disk(&sys_disks)?;
|
||||||
|
// name the disk
|
||||||
|
let mut disk_name = String::new();
|
||||||
|
trace!("{}", disk_name);
|
||||||
|
loop {
|
||||||
|
disk_name = Text::new("Name for the disk:").prompt()?;
|
||||||
|
if storages.iter().all(|s| s.name() != &disk_name) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
println!("The name {} is already used.", disk_name);
|
||||||
|
}
|
||||||
|
trace!("selected name: {}", disk_name);
|
||||||
|
PhysicalDrivePartition::try_from_sysinfo_disk(&disk, disk_name, device)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn select_sysinfo_disk(sysinfo: &sysinfo::System) -> Result<&Disk> {
|
||||||
|
let available_disks = sysinfo
|
||||||
|
.disks()
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, disk)| {
|
||||||
|
let name = match disk.name().to_str() {
|
||||||
|
Some(s) => s,
|
||||||
|
None => "",
|
||||||
|
};
|
||||||
|
let fs: &str = std::str::from_utf8(disk.file_system()).unwrap_or("unknown");
|
||||||
|
let kind = format!("{:?}", disk.kind());
|
||||||
|
let mount_path = disk.mount_point();
|
||||||
|
let total_space = byte_unit::Byte::from_bytes(disk.total_space().into())
|
||||||
|
.get_appropriate_unit(true)
|
||||||
|
.to_string();
|
||||||
|
format!(
|
||||||
|
"{}: {} {} ({}, {}) {}",
|
||||||
|
i,
|
||||||
|
name,
|
||||||
|
total_space,
|
||||||
|
fs,
|
||||||
|
kind,
|
||||||
|
mount_path.display()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
// select from list
|
||||||
|
let disk = inquire::Select::new("Select drive:", available_disks).prompt()?;
|
||||||
|
let disk_num: usize = disk.split(':').next().unwrap().parse().unwrap();
|
||||||
|
trace!("disk_num: {}", disk_num);
|
||||||
|
let disk = sysinfo
|
||||||
|
.disks()
|
||||||
|
.iter()
|
||||||
|
.nth(disk_num)
|
||||||
|
.context("no disk matched with selected one.")?;
|
||||||
|
trace!("selected disk: {:?}", disk);
|
||||||
|
Ok(disk)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue