new: add PhysicalStorage and methods, add flush to gitignore#

This commit is contained in:
qwjyh 2023-08-26 08:40:11 +09:00
parent ff34012eff
commit 2a1854c488
4 changed files with 132 additions and 12 deletions

1
Cargo.lock generated
View file

@ -833,6 +833,7 @@ dependencies = [
"ntapi", "ntapi",
"once_cell", "once_cell",
"rayon", "rayon",
"serde",
"winapi", "winapi",
] ]

View file

@ -7,7 +7,7 @@ edition = "2021"
[dependencies] [dependencies]
clap = { version = "4.4.0", features = ["derive"] } clap = { version = "4.4.0", features = ["derive"] }
sysinfo = "0.29.8" sysinfo = { version = "0.29.8", features = ["serde"] }
log = "0.4" log = "0.4"
clap-verbosity-flag = "2.0.1" clap-verbosity-flag = "2.0.1"
env_logger = "0.10.0" env_logger = "0.10.0"

View file

View file

@ -12,11 +12,15 @@ use inquire::{
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_yaml; use serde_yaml;
use std::fs::{File, OpenOptions};
use std::io::prelude::*; use std::io::prelude::*;
use std::io::{self, BufWriter}; use std::io::{self, BufWriter};
use std::{
collections::{hash_map::RandomState, HashMap},
fmt::Debug,
fs::{File, OpenOptions},
};
use std::{env, io::BufReader, path::Path}; use std::{env, io::BufReader, path::Path};
use sysinfo::{System, SystemExt}; use sysinfo::{DiskExt, System, SystemExt};
#[derive(Parser)] #[derive(Parser)]
#[command(author, version, about, long_about = None)] #[command(author, version, about, long_about = None)]
@ -35,8 +39,25 @@ enum Commands {
repo_url: Option<String>, // url? repo_url: Option<String>, // url?
}, },
Storage(StorageArgs),
/// Print config dir. /// Print config dir.
Path {}, Path {},
/// Sync with git repo.
Sync {},
}
#[derive(clap::Args)]
#[command(args_conflicts_with_subcommands = true)]
struct StorageArgs {
#[command(subcommand)]
command: StorageCommands,
}
#[derive(Subcommand)]
enum StorageCommands {
Add {},
} }
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
@ -47,12 +68,6 @@ struct Device {
hostname: String, hostname: String,
} }
const DEVICESFILE: &str = "devices.yml";
struct Storage {}
struct BackupLog {}
impl Device { impl Device {
fn new(name: String) -> Device { fn new(name: String) -> Device {
let sys = System::new(); let sys = System::new();
@ -74,6 +89,85 @@ impl Device {
} }
} }
const DEVICESFILE: &str = "devices.yml";
/// All storage types.
#[derive(Serialize, Deserialize, Debug)]
enum Storage {
PhysicalStorage(PhysicalDrivePartition),
// /// Online storage provided by others.
// OnlineStorage {
// name: String,
// provider: String,
// capacity: u8,
// },
}
/// Partitoin of physical (on-premises) drive.
#[derive(Serialize, Deserialize, Debug)]
struct PhysicalDrivePartition {
name: String,
kind: String,
capacity: u64,
fs: String,
is_removable: bool,
aliases: HashMap<String, String, RandomState>,
}
impl PhysicalDrivePartition {
/// Try to get Physical drive info from sysinfo.
fn try_from_sysinfo_disk(
disk: sysinfo::Disk,
name: String,
device: Device,
) -> Result<PhysicalDrivePartition, String> {
let alias = match disk.name().to_str() {
Some(s) => s.to_string(),
None => return Err("Failed to convert storage name to valid str.".to_string()),
};
let fs = disk.file_system();
trace!("fs: {:?}", fs);
let fs = match std::str::from_utf8(fs) {
Ok(s) => s,
Err(e) => return Err(e.to_string()),
};
Ok(PhysicalDrivePartition {
name: name,
kind: format!("{:?}", disk.kind()),
capacity: disk.total_space(),
fs: fs.to_string(),
is_removable: disk.is_removable(),
aliases: HashMap::from([(device.name, alias)]),
})
}
fn name(&self) -> &String {
&self.name
}
fn add_alias(self, disk: sysinfo::Disk, device: Device) -> Result<PhysicalDrivePartition, String> {
let alias = match disk.name().to_str() {
Some(s) => s.to_string(),
None => return Err("Failed to convert storage name to valid str.".to_string()),
};
let mut aliases = self.aliases;
let _ = match aliases.insert(device.name, alias) {
Some(v) => v,
None => return Err("Failed to insert alias".to_string()),
};
Ok(PhysicalDrivePartition {
name: self.name,
kind: self.kind,
capacity: self.capacity,
fs: self.fs,
is_removable: self.is_removable,
aliases,
})
}
}
struct BackupLog {}
fn main() -> Result<(), String> { fn main() -> Result<(), String> {
let cli = Cli::parse(); let cli = Cli::parse();
env_logger::Builder::new() env_logger::Builder::new()
@ -123,7 +217,15 @@ fn main() -> Result<(), String> {
Ok(_) => trace!("successfully created ignore file"), Ok(_) => trace!("successfully created ignore file"),
Err(e) => return Err(e.to_string()), Err(e) => return Err(e.to_string()),
}; };
match add_and_commit(&repo, Path::new(".gitignore"), "Add devname to gitignore.") { match buf.flush() {
Ok(_) => (),
Err(e) => return Err(e.to_string()),
};
match add_and_commit(
&repo,
Path::new(".gitignore"),
"Add devname to gitignore.",
) {
Ok(_) => (), Ok(_) => (),
Err(e) => return Err(e.to_string()), Err(e) => return Err(e.to_string()),
}; };
@ -154,6 +256,9 @@ fn main() -> Result<(), String> {
} else { } else {
get_devices(&config_dir)? get_devices(&config_dir)?
}; };
if devices.iter().any(|x| x.name == device.name) {
return Err("device name is already used.".to_string());
}
devices.push(device.clone()); devices.push(device.clone());
trace!("Devices: {:?}", devices); trace!("Devices: {:?}", devices);
write_devices(&config_dir, devices)?; write_devices(&config_dir, devices)?;
@ -169,9 +274,19 @@ fn main() -> Result<(), String> {
Err(e) => return Err(e.to_string()), Err(e) => return Err(e.to_string()),
} }
} }
Commands::Storage(storage) => {
match storage.command {
StorageCommands::Add {} => {
unimplemented!()
}
}
}
Commands::Path {} => { Commands::Path {} => {
println!("{}", &config_dir.display()); println!("{}", &config_dir.display());
} }
Commands::Sync {} => {
unimplemented!("Sync is not implemented")
}
} }
Ok(()) Ok(())
} }
@ -226,7 +341,11 @@ fn get_devices(config_dir: &Path) -> Result<Vec<Device>, String> {
/// Write `devices` to yaml file in `config_dir`. /// Write `devices` to yaml file in `config_dir`.
fn write_devices(config_dir: &Path, devices: Vec<Device>) -> Result<(), String> { fn write_devices(config_dir: &Path, devices: Vec<Device>) -> Result<(), String> {
trace!("write_devices"); trace!("write_devices");
let f = match OpenOptions::new().create(true).write(true).open(config_dir.join(DEVICESFILE)) { let f = match OpenOptions::new()
.create(true)
.write(true)
.open(config_dir.join(DEVICESFILE))
{
Ok(f) => f, Ok(f) => f,
Err(e) => return Err(e.to_string()), Err(e) => return Err(e.to_string()),
}; };