mirror of
https://github.com/qwjyh/xdbm
synced 2024-11-22 06:40:12 +09:00
online storage & fix directory parent find & and so on
This commit is contained in:
parent
83233740aa
commit
b54cbf00f0
5 changed files with 99 additions and 36 deletions
11
src/main.rs
11
src/main.rs
|
@ -12,16 +12,13 @@ extern crate log;
|
||||||
extern crate dirs;
|
extern crate dirs;
|
||||||
|
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use byte_unit::Byte;
|
|
||||||
use clap::error::ErrorKind;
|
use clap::error::ErrorKind;
|
||||||
use clap::{CommandFactory, Parser, Subcommand};
|
use clap::{CommandFactory, Parser, Subcommand};
|
||||||
use clap_verbosity_flag::Verbosity;
|
use clap_verbosity_flag::Verbosity;
|
||||||
use git2::{Commit, Oid, Repository};
|
use git2::{Commit, Oid, Repository};
|
||||||
use inquire::{validator::Validation, Text};
|
use inquire::{validator::Validation, Text};
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use serde_yaml;
|
use serde_yaml;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::format;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::{env, io::BufReader, path::Path};
|
use std::{env, io::BufReader, path::Path};
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -33,8 +30,8 @@ use std::{fs, io::prelude::*};
|
||||||
use sysinfo::{Disk, DiskExt, SystemExt};
|
use sysinfo::{Disk, DiskExt, SystemExt};
|
||||||
|
|
||||||
use crate::storages::{
|
use crate::storages::{
|
||||||
directory::Directory, get_storages, local_info, physical_drive_partition::*, write_storages,
|
directory::Directory, get_storages, local_info, online_storage, physical_drive_partition::*,
|
||||||
Storage, StorageExt, StorageType, STORAGESFILE,
|
write_storages, Storage, StorageExt, StorageType, STORAGESFILE,
|
||||||
};
|
};
|
||||||
use devices::{Device, DEVICESFILE, *};
|
use devices::{Device, DEVICESFILE, *};
|
||||||
|
|
||||||
|
@ -81,6 +78,7 @@ enum StorageCommands {
|
||||||
#[arg(value_enum)]
|
#[arg(value_enum)]
|
||||||
storage_type: StorageType,
|
storage_type: StorageType,
|
||||||
|
|
||||||
|
// TODO: set this require and select matching disk for physical
|
||||||
#[arg(short, long, value_name = "PATH")]
|
#[arg(short, long, value_name = "PATH")]
|
||||||
path: Option<PathBuf>,
|
path: Option<PathBuf>,
|
||||||
},
|
},
|
||||||
|
@ -235,6 +233,7 @@ fn main() -> Result<()> {
|
||||||
)?;
|
)?;
|
||||||
(key_name, Storage::SubDirectory(storage))
|
(key_name, Storage::SubDirectory(storage))
|
||||||
}
|
}
|
||||||
|
StorageType::Online => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// add to storages
|
// add to storages
|
||||||
|
@ -283,7 +282,7 @@ fn main() -> Result<()> {
|
||||||
.to_str()
|
.to_str()
|
||||||
.context("Failed to convert disk name to valid string")?;
|
.context("Failed to convert disk name to valid string")?;
|
||||||
// add to storages
|
// add to storages
|
||||||
storage.add_alias(disk, &config_dir)?;
|
storage.bind_device(disk, &config_dir)?;
|
||||||
trace!("storage: {}", storage);
|
trace!("storage: {}", storage);
|
||||||
format!("{} to {}", system_name, storage.name())
|
format!("{} to {}", system_name, storage.name())
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
//! Manipulates storages.
|
//! Manipulates storages.
|
||||||
|
|
||||||
use crate::storages::physical_drive_partition::PhysicalDrivePartition;
|
|
||||||
use crate::storages::directory::Directory;
|
|
||||||
use crate::devices;
|
use crate::devices;
|
||||||
|
use crate::storages::directory::Directory;
|
||||||
|
use crate::storages::online_storage::OnlineStorage;
|
||||||
|
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};
|
||||||
|
@ -15,7 +16,7 @@ pub const STORAGESFILE: &str = "storages.yml";
|
||||||
pub enum StorageType {
|
pub enum StorageType {
|
||||||
Physical,
|
Physical,
|
||||||
SubDirectory,
|
SubDirectory,
|
||||||
// Online,
|
Online,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All storage types.
|
/// All storage types.
|
||||||
|
@ -23,24 +24,20 @@ pub enum StorageType {
|
||||||
pub enum Storage {
|
pub enum Storage {
|
||||||
PhysicalStorage(PhysicalDrivePartition),
|
PhysicalStorage(PhysicalDrivePartition),
|
||||||
SubDirectory(Directory),
|
SubDirectory(Directory),
|
||||||
// /// Online storage provided by others.
|
Online(OnlineStorage),
|
||||||
// OnlineStorage {
|
|
||||||
// name: String,
|
|
||||||
// provider: String,
|
|
||||||
// capacity: u8,
|
|
||||||
// },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Storage {
|
impl Storage {
|
||||||
/// Add or update alias of `disk` for current device.
|
/// Add or update alias of `disk` for current device.
|
||||||
pub fn add_alias(
|
pub fn bind_device(
|
||||||
&mut self,
|
&mut self,
|
||||||
disk: &sysinfo::Disk,
|
disk: &sysinfo::Disk,
|
||||||
config_dir: &std::path::PathBuf,
|
config_dir: &std::path::PathBuf,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
Self::PhysicalStorage(s) => s.add_alias(disk, config_dir),
|
Self::PhysicalStorage(s) => s.bind_device(disk, config_dir),
|
||||||
Self::SubDirectory(_) => Err(anyhow!("SubDirectory doesn't have system alias.")),
|
Self::SubDirectory(_) => Err(anyhow!("SubDirectory doesn't have system alias.")),
|
||||||
|
Self::Online(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,16 +47,15 @@ impl StorageExt for Storage {
|
||||||
match self {
|
match self {
|
||||||
Self::PhysicalStorage(s) => s.name(),
|
Self::PhysicalStorage(s) => s.name(),
|
||||||
Self::SubDirectory(s) => s.name(),
|
Self::SubDirectory(s) => s.name(),
|
||||||
|
Self::Online(s) => s.name(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_alias(
|
fn has_alias(&self, device: &devices::Device) -> bool {
|
||||||
&self,
|
|
||||||
device: &devices::Device,
|
|
||||||
) -> bool {
|
|
||||||
match self {
|
match self {
|
||||||
Self::PhysicalStorage(s) => s.has_alias(&device),
|
Self::PhysicalStorage(s) => s.has_alias(&device),
|
||||||
Self::SubDirectory(s) => s.has_alias(&device),
|
Self::SubDirectory(s) => s.has_alias(&device),
|
||||||
|
Self::Online(s) => s.has_alias(&device),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +67,7 @@ impl StorageExt for Storage {
|
||||||
match self {
|
match self {
|
||||||
Self::PhysicalStorage(s) => s.mount_path(&device, &storages),
|
Self::PhysicalStorage(s) => s.mount_path(&device, &storages),
|
||||||
Self::SubDirectory(s) => s.mount_path(&device, &storages),
|
Self::SubDirectory(s) => s.mount_path(&device, &storages),
|
||||||
|
Self::Online(s) => s.mount_path(&device, &storages),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,6 +77,7 @@ impl fmt::Display for Storage {
|
||||||
match self {
|
match self {
|
||||||
Self::PhysicalStorage(s) => s.fmt(f),
|
Self::PhysicalStorage(s) => s.fmt(f),
|
||||||
Self::SubDirectory(s) => s.fmt(f),
|
Self::SubDirectory(s) => s.fmt(f),
|
||||||
|
Self::Online(s) => s.fmt(f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,6 +86,7 @@ impl fmt::Display for Storage {
|
||||||
pub trait StorageExt {
|
pub trait StorageExt {
|
||||||
fn name(&self) -> &String;
|
fn name(&self) -> &String;
|
||||||
fn has_alias(&self, device: &devices::Device) -> bool;
|
fn has_alias(&self, device: &devices::Device) -> bool;
|
||||||
|
/// Get mount path of `self` on `device`.
|
||||||
fn mount_path(
|
fn mount_path(
|
||||||
&self,
|
&self,
|
||||||
device: &devices::Device,
|
device: &devices::Device,
|
||||||
|
@ -97,6 +96,7 @@ pub trait StorageExt {
|
||||||
|
|
||||||
pub mod directory;
|
pub mod directory;
|
||||||
pub mod local_info;
|
pub mod local_info;
|
||||||
|
pub mod online_storage;
|
||||||
pub mod physical_drive_partition;
|
pub mod physical_drive_partition;
|
||||||
|
|
||||||
/// Get `Vec<Storage>` from devices.yml([DEVICESFILE]).
|
/// Get `Vec<Storage>` from devices.yml([DEVICESFILE]).
|
||||||
|
|
|
@ -2,13 +2,7 @@
|
||||||
|
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{collections::HashMap, fmt, path};
|
||||||
collections::HashMap,
|
|
||||||
fmt::{self, write},
|
|
||||||
hash::Hash,
|
|
||||||
path,
|
|
||||||
rc::Rc,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::devices;
|
use crate::devices;
|
||||||
|
|
||||||
|
@ -31,7 +25,7 @@ impl Directory {
|
||||||
/// - `notes`: supplimental notes.
|
/// - `notes`: supplimental notes.
|
||||||
fn new(
|
fn new(
|
||||||
name: String,
|
name: String,
|
||||||
parent: String, // todo implement serialize
|
parent: String,
|
||||||
relative_path: path::PathBuf,
|
relative_path: path::PathBuf,
|
||||||
notes: String,
|
notes: String,
|
||||||
local_info: HashMap<String, LocalInfo>,
|
local_info: HashMap<String, LocalInfo>,
|
||||||
|
@ -58,7 +52,11 @@ impl Directory {
|
||||||
.filter_map(|(k, v)| {
|
.filter_map(|(k, v)| {
|
||||||
let diff = pathdiff::diff_paths(&path, v.mount_path(&device, &storages).unwrap())?;
|
let diff = pathdiff::diff_paths(&path, v.mount_path(&device, &storages).unwrap())?;
|
||||||
trace!("Pathdiff: {:?}", diff);
|
trace!("Pathdiff: {:?}", diff);
|
||||||
Some((k, diff))
|
if diff.components().any(|c| c == path::Component::ParentDir) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some((k, diff))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.min_by_key(|(_k, v)| {
|
.min_by_key(|(_k, v)| {
|
||||||
let diff_paths: Vec<path::Component<'_>> = v.components().collect();
|
let diff_paths: Vec<path::Component<'_>> = v.components().collect();
|
||||||
|
@ -106,6 +104,16 @@ 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 {
|
||||||
|
|
61
src/storages/online_storage.rs
Normal file
61
src/storages/online_storage.rs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
//! Online storage which is not a children of any physical drive.
|
||||||
|
|
||||||
|
use anyhow::Context;
|
||||||
|
use byte_unit::Byte;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fmt;
|
||||||
|
use std::path;
|
||||||
|
|
||||||
|
use crate::devices;
|
||||||
|
|
||||||
|
use super::local_info::LocalInfo;
|
||||||
|
use super::StorageExt;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct OnlineStorage {
|
||||||
|
name: String,
|
||||||
|
provider: String,
|
||||||
|
capacity: u8,
|
||||||
|
local_info: HashMap<String, LocalInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OnlineStorage {
|
||||||
|
fn new(name: String, provider: String, capacity: u8, path: path::PathBuf, device: &devices::Device) -> OnlineStorage {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StorageExt for OnlineStorage {
|
||||||
|
fn name(&self) -> &String {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_alias(&self, device: &devices::Device) -> bool {
|
||||||
|
self.local_info.get(&device.name()).is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mount_path(
|
||||||
|
&self,
|
||||||
|
device: &devices::Device,
|
||||||
|
_storages: &HashMap<String, super::Storage>,
|
||||||
|
) -> anyhow::Result<std::path::PathBuf> {
|
||||||
|
Ok(self
|
||||||
|
.local_info
|
||||||
|
.get(&device.name())
|
||||||
|
.context(format!("LocalInfo for storage: {} not found", &self.name()))?
|
||||||
|
.mount_path())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for OnlineStorage {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"O {name:<10} {size} {provider:<10}",
|
||||||
|
name = self.name(),
|
||||||
|
size = Byte::from_bytes(self.capacity.into()).get_appropriate_unit(true),
|
||||||
|
provider = self.provider,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,11 +28,6 @@ pub struct PhysicalDrivePartition {
|
||||||
local_info: HashMap<String, LocalInfo>,
|
local_info: HashMap<String, LocalInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PhysicalDrivePartitionLocal {
|
|
||||||
alias: String,
|
|
||||||
mount_path: path::PathBuf,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PhysicalDrivePartition {
|
impl PhysicalDrivePartition {
|
||||||
/// Try to get Physical drive info from sysinfo.
|
/// Try to get Physical drive info from sysinfo.
|
||||||
pub fn try_from_sysinfo_disk(
|
pub fn try_from_sysinfo_disk(
|
||||||
|
@ -60,7 +55,7 @@ impl PhysicalDrivePartition {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_alias(
|
pub fn bind_device(
|
||||||
&mut self,
|
&mut self,
|
||||||
disk: &sysinfo::Disk,
|
disk: &sysinfo::Disk,
|
||||||
config_dir: &std::path::PathBuf,
|
config_dir: &std::path::PathBuf,
|
||||||
|
|
Loading…
Reference in a new issue