mirror of
https://github.com/qwjyh/xdbm
synced 2024-11-22 06:40:12 +09:00
[refactor] separate subcommands to other file
This commit is contained in:
parent
b949cca1e8
commit
ff72228821
3 changed files with 359 additions and 295 deletions
85
src/cmd_init.rs
Normal file
85
src/cmd_init.rs
Normal file
|
@ -0,0 +1,85 @@
|
|||
//! Init subcommand.
|
||||
//! Initialize xdbm for the device.
|
||||
|
||||
use crate::{
|
||||
add_and_commit, full_status, get_devices, set_device_name, write_devices, Device, DEVICESFILE,
|
||||
};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use git2::Repository;
|
||||
use std::fs::File;
|
||||
use std::io::{BufWriter, Write};
|
||||
use std::path::{self, Path};
|
||||
|
||||
pub(crate) fn cmd_init(repo_url: Option<String>, config_dir: &path::PathBuf) -> Result<()> {
|
||||
let is_first_device: bool;
|
||||
// get repo or initialize it
|
||||
let repo = match repo_url {
|
||||
Some(repo_url) => {
|
||||
trace!("repo: {}", repo_url);
|
||||
let repo = Repository::clone(&repo_url, &config_dir)?;
|
||||
is_first_device = false;
|
||||
repo
|
||||
}
|
||||
None => {
|
||||
trace!("No repo provided");
|
||||
println!("Initializing for the first device...");
|
||||
|
||||
// create repository
|
||||
let repo = Repository::init(&config_dir)?;
|
||||
|
||||
// set up gitignore
|
||||
{
|
||||
let f = File::create(&config_dir.join(".gitignore"))?;
|
||||
{
|
||||
let mut buf = BufWriter::new(f);
|
||||
buf.write("devname".as_bytes())?;
|
||||
}
|
||||
add_and_commit(&repo, Path::new(".gitignore"), "Add devname to gitignore.")?;
|
||||
full_status(&repo)?;
|
||||
}
|
||||
is_first_device = true;
|
||||
repo
|
||||
}
|
||||
};
|
||||
full_status(&repo)?;
|
||||
|
||||
// set device name
|
||||
let device = set_device_name()?;
|
||||
|
||||
// save devname
|
||||
let devname_path = &config_dir.join("devname");
|
||||
{
|
||||
let f = File::create(devname_path)
|
||||
.context("Failed to create a file to store local device name")?;
|
||||
let writer = BufWriter::new(f);
|
||||
serde_yaml::to_writer(writer, &device.name()).unwrap();
|
||||
};
|
||||
full_status(&repo)?;
|
||||
|
||||
// Add new device to devices.yml
|
||||
{
|
||||
let mut devices: Vec<Device> = if is_first_device {
|
||||
vec![]
|
||||
} else {
|
||||
get_devices(&config_dir)?
|
||||
};
|
||||
trace!("devices: {:?}", devices);
|
||||
if devices.iter().any(|x| x.name() == device.name()) {
|
||||
return Err(anyhow!("device name is already used."));
|
||||
}
|
||||
devices.push(device.clone());
|
||||
trace!("Devices: {:?}", devices);
|
||||
write_devices(&config_dir, devices)?;
|
||||
}
|
||||
full_status(&repo)?;
|
||||
|
||||
// commit
|
||||
add_and_commit(
|
||||
&repo,
|
||||
&Path::new(DEVICESFILE),
|
||||
&format!("Add new devname: {}", &device.name()),
|
||||
)?;
|
||||
println!("Device added");
|
||||
full_status(&repo)?;
|
||||
Ok(())
|
||||
}
|
252
src/cmd_storage.rs
Normal file
252
src/cmd_storage.rs
Normal file
|
@ -0,0 +1,252 @@
|
|||
//! Storage subcommands.
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use clap::{error::ErrorKind, CommandFactory};
|
||||
use git2::Repository;
|
||||
use inquire::{min_length, Confirm, CustomType, Select, Text};
|
||||
|
||||
use crate::{
|
||||
add_and_commit, ask_unique_name,
|
||||
cmd_args::Cli,
|
||||
get_device,
|
||||
inquire_filepath_completer::FilePathCompleter,
|
||||
storages::{
|
||||
self, directory, get_storages, local_info, physical_drive_partition, Storage, StorageExt,
|
||||
StorageType,
|
||||
},
|
||||
};
|
||||
|
||||
pub(crate) fn cmd_storage_add(
|
||||
storage_type: storages::StorageType,
|
||||
path: Option<PathBuf>,
|
||||
repo: Repository,
|
||||
config_dir: &PathBuf,
|
||||
) -> Result<()> {
|
||||
trace!("Storage Add {:?}, {:?}", storage_type, path);
|
||||
// Get storages
|
||||
// let mut storages: Vec<Storage> = get_storages(&config_dir)?;
|
||||
let mut storages: HashMap<String, Storage> = get_storages(&config_dir)?;
|
||||
trace!("found storages: {:?}", storages);
|
||||
|
||||
let device = get_device(&config_dir)?;
|
||||
let (key, storage) = match storage_type {
|
||||
StorageType::Physical => {
|
||||
let use_sysinfo = {
|
||||
let options = vec![
|
||||
"Fetch disk information automatically.",
|
||||
"Type disk information manually.",
|
||||
];
|
||||
let ans = Select::new(
|
||||
"Do you fetch disk information automatically? (it may take a few minutes)",
|
||||
options,
|
||||
)
|
||||
.prompt()
|
||||
.context("Failed to get response. Please try again.")?;
|
||||
match ans {
|
||||
"Fetch disk information automatically." => true,
|
||||
_ => false,
|
||||
}
|
||||
};
|
||||
let (key, storage) = if use_sysinfo {
|
||||
// select storage
|
||||
physical_drive_partition::select_physical_storage(device, &storages)?
|
||||
} else {
|
||||
let mut name = String::new();
|
||||
loop {
|
||||
name = Text::new("Name for the storage:")
|
||||
.with_validator(min_length!(0, "At least 1 character"))
|
||||
.prompt()
|
||||
.context("Failed to get Name")?;
|
||||
if storages.iter().all(|(k, _v)| k != &name) {
|
||||
break;
|
||||
}
|
||||
println!("The name {} is already used.", name);
|
||||
}
|
||||
let kind = Text::new("Kind of storage (ex. SSD):")
|
||||
.prompt()
|
||||
.context("Failed to get kind.")?;
|
||||
let capacity: u64 = CustomType::<u64>::new("Capacity (byte):")
|
||||
.with_error_message("Please type number.")
|
||||
.prompt()
|
||||
.context("Failed to get capacity.")?;
|
||||
let fs = Text::new("filesystem:")
|
||||
.prompt()
|
||||
.context("Failed to get fs.")?;
|
||||
let is_removable = Confirm::new("Is removable")
|
||||
.prompt()
|
||||
.context("Failed to get is_removable")?;
|
||||
let mount_path: PathBuf = PathBuf::from(
|
||||
Text::new("mount path:")
|
||||
.with_autocomplete(FilePathCompleter::default())
|
||||
.prompt()?,
|
||||
);
|
||||
let local_info = local_info::LocalInfo::new("".to_string(), mount_path);
|
||||
(
|
||||
name.clone(),
|
||||
physical_drive_partition::PhysicalDrivePartition::new(
|
||||
name,
|
||||
kind,
|
||||
capacity,
|
||||
fs,
|
||||
is_removable,
|
||||
local_info,
|
||||
&device,
|
||||
),
|
||||
)
|
||||
};
|
||||
println!("storage: {}: {:?}", key, storage);
|
||||
(key, Storage::PhysicalStorage(storage))
|
||||
}
|
||||
StorageType::SubDirectory => {
|
||||
if storages.is_empty() {
|
||||
return Err(anyhow!(
|
||||
"No storages found. Please add at least 1 physical storage first."
|
||||
));
|
||||
}
|
||||
let path = path.unwrap_or_else(|| {
|
||||
let mut cmd = Cli::command();
|
||||
cmd.error(
|
||||
ErrorKind::MissingRequiredArgument,
|
||||
"<PATH> is required with sub-directory",
|
||||
)
|
||||
.exit();
|
||||
});
|
||||
trace!("SubDirectory arguments: path: {:?}", path);
|
||||
// Nightly feature std::path::absolute
|
||||
let path = path.canonicalize()?;
|
||||
trace!("canonicalized: path: {:?}", path);
|
||||
|
||||
let key_name = ask_unique_name(&storages, "sub-directory".to_string())?;
|
||||
let notes = Text::new("Notes for this sub-directory:").prompt()?;
|
||||
let storage = directory::Directory::try_from_device_path(
|
||||
key_name.clone(),
|
||||
path,
|
||||
notes,
|
||||
&device,
|
||||
&storages,
|
||||
)?;
|
||||
(key_name, Storage::SubDirectory(storage))
|
||||
}
|
||||
StorageType::Online => {
|
||||
let path = path.unwrap_or_else(|| {
|
||||
let mut cmd = Cli::command();
|
||||
cmd.error(
|
||||
ErrorKind::MissingRequiredArgument,
|
||||
"<PATH> is required with sub-directory",
|
||||
)
|
||||
.exit();
|
||||
});
|
||||
let mut name = String::new();
|
||||
loop {
|
||||
name = Text::new("Name for the storage:")
|
||||
.with_validator(min_length!(0, "At least 1 character"))
|
||||
.prompt()
|
||||
.context("Failed to get Name")?;
|
||||
if storages.iter().all(|(k, _v)| k != &name) {
|
||||
break;
|
||||
}
|
||||
println!("The name {} is already used.", name);
|
||||
}
|
||||
let provider = Text::new("Provider:")
|
||||
.prompt()
|
||||
.context("Failed to get provider")?;
|
||||
let capacity: u64 = CustomType::<u64>::new("Capacity (byte):")
|
||||
.with_error_message("Please type number.")
|
||||
.prompt()
|
||||
.context("Failed to get capacity.")?;
|
||||
let alias = Text::new("Alias:")
|
||||
.prompt()
|
||||
.context("Failed to get provider")?;
|
||||
let storage = storages::online_storage::OnlineStorage::new(
|
||||
name.clone(),
|
||||
provider,
|
||||
capacity,
|
||||
alias,
|
||||
path,
|
||||
&device,
|
||||
);
|
||||
(name, Storage::Online(storage))
|
||||
}
|
||||
};
|
||||
|
||||
// add to storages
|
||||
storages.insert(key.clone(), storage);
|
||||
trace!("updated storages: {:?}", storages);
|
||||
|
||||
// write to file
|
||||
storages::write_storages(&config_dir, storages)?;
|
||||
|
||||
// commit
|
||||
add_and_commit(
|
||||
&repo,
|
||||
&Path::new(storages::STORAGESFILE),
|
||||
&format!("Add new storage(physical drive): {}", key),
|
||||
)?;
|
||||
|
||||
println!("Added new storage.");
|
||||
trace!("Finished adding storage");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn cmd_storage_list(config_dir: &PathBuf) -> Result<()> {
|
||||
// Get storages
|
||||
let storages: HashMap<String, Storage> = get_storages(&config_dir)?;
|
||||
trace!("found storages: {:?}", storages);
|
||||
let device = get_device(&config_dir)?;
|
||||
for (k, storage) in &storages {
|
||||
println!("{}: {}", k, storage);
|
||||
println!(" {}", storage.mount_path(&device, &storages)?.display());
|
||||
// println!("{}: {}", storage.shorttypename(), storage.name()); // TODO
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn cmd_storage_bind(
|
||||
storage_name: String,
|
||||
new_alias: String,
|
||||
mount_point: PathBuf,
|
||||
repo: Repository,
|
||||
config_dir: &PathBuf,
|
||||
) -> Result<()> {
|
||||
let device = get_device(&config_dir)?;
|
||||
// get storages
|
||||
let mut storages: HashMap<String, Storage> = get_storages(&config_dir)?;
|
||||
let commit_comment = {
|
||||
// find matching storage
|
||||
let storage = &mut storages
|
||||
.get_mut(&storage_name)
|
||||
.context(format!("No storage has name {}", storage_name))?;
|
||||
let old_alias = storage
|
||||
.local_info(&device)
|
||||
.context(format!("Failed to get LocalInfo for {}", storage.name()))?
|
||||
.alias()
|
||||
.clone();
|
||||
// TODO: get mount path for directory automatically?
|
||||
storage.bound_on_device(new_alias, mount_point, &device)?;
|
||||
// trace!("storage: {}", &storage);
|
||||
format!("{} to {}", old_alias, storage.name())
|
||||
};
|
||||
trace!("bound new system name to the storage");
|
||||
trace!("storages: {:#?}", storages);
|
||||
|
||||
storages::write_storages(&config_dir, storages)?;
|
||||
// commit
|
||||
add_and_commit(
|
||||
&repo,
|
||||
&Path::new(storages::STORAGESFILE),
|
||||
&format!(
|
||||
"Bound new storage name to physical drive ({})",
|
||||
commit_comment
|
||||
),
|
||||
)?;
|
||||
println!(
|
||||
"Bound new storage name to physical drive ({})",
|
||||
commit_comment
|
||||
);
|
||||
Ok(())
|
||||
}
|
317
src/main.rs
317
src/main.rs
|
@ -1,8 +1,9 @@
|
|||
//! # Main types
|
||||
//! * [Device]: represents PC.
|
||||
//! * [Device]: represents PC. module [devices]
|
||||
//! * [Storage]: all storages. module [storages]
|
||||
//! * [PhysicalDrivePartition]: partition on a physical disk. [storages::physical_drive_partition]
|
||||
//! * [Directory]: sub-directory of other storages. [storages::directory]
|
||||
//! * [physical_drive_partition::PhysicalDrivePartition]: partition on a physical disk. module [storages::physical_drive_partition]
|
||||
//! * [directory::Directory]: sub-directory of other storages. module [storages::directory]
|
||||
//! * [online_storage::OnlineStorage]: online storage like Google Drive. module [storages::online_storage]
|
||||
//! * [storages::local_info::LocalInfo]: stores [Device] specific common data for [Storage]s.
|
||||
//!
|
||||
|
||||
|
@ -19,23 +20,21 @@ use inquire::{min_length, Confirm, CustomType, Select};
|
|||
use inquire::{validator::Validation, Text};
|
||||
use serde_yaml;
|
||||
use std::collections::HashMap;
|
||||
use std::io::{self, BufWriter};
|
||||
use std::path::Path;
|
||||
use std::path::{self, PathBuf};
|
||||
use std::{env, io::BufReader, path::Path};
|
||||
use std::{fmt::Debug, fs::File};
|
||||
use std::{fs, io::prelude::*};
|
||||
use sysinfo::{Disk, DiskExt, SystemExt};
|
||||
|
||||
use crate::cmd_args::{Cli, Commands, StorageArgs, StorageCommands};
|
||||
use crate::inquire_filepath_completer::FilePathCompleter;
|
||||
use crate::storages::online_storage::OnlineStorage;
|
||||
use crate::cmd_args::{Cli, Commands, StorageCommands};
|
||||
use crate::cmd_storage;
|
||||
use crate::storages::online_storage;
|
||||
use crate::storages::{
|
||||
directory::Directory, get_storages, local_info, online_storage, physical_drive_partition::*,
|
||||
write_storages, Storage, StorageExt, StorageType, STORAGESFILE,
|
||||
directory, get_storages, local_info, physical_drive_partition, write_storages, Storage,
|
||||
StorageExt, StorageType, STORAGESFILE,
|
||||
};
|
||||
use devices::{Device, DEVICESFILE, *};
|
||||
|
||||
mod cmd_args;
|
||||
mod cmd_init;
|
||||
mod cmd_storage;
|
||||
mod devices;
|
||||
mod inquire_filepath_completer;
|
||||
mod storages;
|
||||
|
@ -55,82 +54,7 @@ fn main() -> Result<()> {
|
|||
trace!("Config dir: {:?}", config_dir);
|
||||
|
||||
match cli.command {
|
||||
Commands::Init { repo_url } => {
|
||||
let is_first_device: bool;
|
||||
// get repo or initialize it
|
||||
let repo = match repo_url {
|
||||
Some(repo_url) => {
|
||||
trace!("repo: {}", repo_url);
|
||||
let repo = Repository::clone(&repo_url, &config_dir)?;
|
||||
is_first_device = false;
|
||||
repo
|
||||
}
|
||||
None => {
|
||||
trace!("No repo provided");
|
||||
println!("Initializing for the first device...");
|
||||
|
||||
// create repository
|
||||
let repo = Repository::init(&config_dir)?;
|
||||
|
||||
// set up gitignore
|
||||
{
|
||||
let f = File::create(&config_dir.join(".gitignore"))?;
|
||||
{
|
||||
let mut buf = BufWriter::new(f);
|
||||
buf.write("devname".as_bytes())?;
|
||||
}
|
||||
add_and_commit(
|
||||
&repo,
|
||||
Path::new(".gitignore"),
|
||||
"Add devname to gitignore.",
|
||||
)?;
|
||||
full_status(&repo)?;
|
||||
}
|
||||
is_first_device = true;
|
||||
repo
|
||||
}
|
||||
};
|
||||
full_status(&repo)?;
|
||||
|
||||
// set device name
|
||||
let device = set_device_name()?;
|
||||
|
||||
// save devname
|
||||
let devname_path = &config_dir.join("devname");
|
||||
{
|
||||
let f = File::create(devname_path)
|
||||
.context("Failed to create a file to store local device name")?;
|
||||
let writer = BufWriter::new(f);
|
||||
serde_yaml::to_writer(writer, &device.name()).unwrap();
|
||||
};
|
||||
full_status(&repo)?;
|
||||
|
||||
// Add new device to devices.yml
|
||||
{
|
||||
let mut devices: Vec<Device> = if is_first_device {
|
||||
vec![]
|
||||
} else {
|
||||
get_devices(&config_dir)?
|
||||
};
|
||||
trace!("devices: {:?}", devices);
|
||||
if devices.iter().any(|x| x.name() == device.name()) {
|
||||
return Err(anyhow!("device name is already used."));
|
||||
}
|
||||
devices.push(device.clone());
|
||||
trace!("Devices: {:?}", devices);
|
||||
write_devices(&config_dir, devices)?;
|
||||
}
|
||||
full_status(&repo)?;
|
||||
|
||||
// commit
|
||||
add_and_commit(
|
||||
&repo,
|
||||
&Path::new(DEVICESFILE),
|
||||
&format!("Add new devname: {}", &device.name()),
|
||||
)?;
|
||||
println!("Device added");
|
||||
full_status(&repo)?;
|
||||
}
|
||||
Commands::Init { repo_url } => cmd_init::cmd_init(repo_url, &config_dir)?,
|
||||
Commands::Storage(storage) => {
|
||||
let repo = Repository::open(&config_dir).context(
|
||||
"Repository doesn't exist. Please run init to initialize the repository.",
|
||||
|
@ -138,217 +62,20 @@ fn main() -> Result<()> {
|
|||
trace!("repo state: {:?}", repo.state());
|
||||
match storage.command {
|
||||
StorageCommands::Add { storage_type, path } => {
|
||||
trace!("Storage Add {:?}, {:?}", storage_type, path);
|
||||
// Get storages
|
||||
// let mut storages: Vec<Storage> = get_storages(&config_dir)?;
|
||||
let mut storages: HashMap<String, Storage> = get_storages(&config_dir)?;
|
||||
trace!("found storages: {:?}", storages);
|
||||
|
||||
let device = get_device(&config_dir)?;
|
||||
let (key, storage) = match storage_type {
|
||||
StorageType::Physical => {
|
||||
let use_sysinfo = {
|
||||
let options = vec![
|
||||
"Fetch disk information automatically.",
|
||||
"Type disk information manually.",
|
||||
];
|
||||
let ans = Select::new("Do you fetch disk information automatically? (it may take a few minutes)", options)
|
||||
.prompt().context("Failed to get response. Please try again.")?;
|
||||
match ans {
|
||||
"Fetch disk information automatically." => true,
|
||||
_ => false,
|
||||
}
|
||||
};
|
||||
let (key, storage) = if use_sysinfo {
|
||||
// select storage
|
||||
select_physical_storage(device, &storages)?
|
||||
} else {
|
||||
let mut name = String::new();
|
||||
loop {
|
||||
name = Text::new("Name for the storage:")
|
||||
.with_validator(min_length!(0, "At least 1 character"))
|
||||
.prompt()
|
||||
.context("Failed to get Name")?;
|
||||
if storages.iter().all(|(k, _v)| k != &name) {
|
||||
break;
|
||||
}
|
||||
println!("The name {} is already used.", name);
|
||||
}
|
||||
let kind = Text::new("Kind of storage (ex. SSD):")
|
||||
.prompt()
|
||||
.context("Failed to get kind.")?;
|
||||
let capacity: u64 = CustomType::<u64>::new("Capacity (byte):")
|
||||
.with_error_message("Please type number.")
|
||||
.prompt()
|
||||
.context("Failed to get capacity.")?;
|
||||
let fs = Text::new("filesystem:")
|
||||
.prompt()
|
||||
.context("Failed to get fs.")?;
|
||||
let is_removable = Confirm::new("Is removable")
|
||||
.prompt()
|
||||
.context("Failed to get is_removable")?;
|
||||
let mount_path: path::PathBuf = PathBuf::from(
|
||||
Text::new("mount path:")
|
||||
.with_autocomplete(FilePathCompleter::default())
|
||||
.prompt()?,
|
||||
);
|
||||
let local_info =
|
||||
local_info::LocalInfo::new("".to_string(), mount_path);
|
||||
(
|
||||
name.clone(),
|
||||
PhysicalDrivePartition::new(
|
||||
name,
|
||||
kind,
|
||||
capacity,
|
||||
fs,
|
||||
is_removable,
|
||||
local_info,
|
||||
&device,
|
||||
),
|
||||
)
|
||||
};
|
||||
println!("storage: {}: {:?}", key, storage);
|
||||
(key, Storage::PhysicalStorage(storage))
|
||||
}
|
||||
StorageType::SubDirectory => {
|
||||
if storages.is_empty() {
|
||||
return Err(anyhow!("No storages found. Please add at least 1 physical storage first."));
|
||||
}
|
||||
let path = path.unwrap_or_else(|| {
|
||||
let mut cmd = Cli::command();
|
||||
cmd.error(
|
||||
ErrorKind::MissingRequiredArgument,
|
||||
"<PATH> is required with sub-directory",
|
||||
)
|
||||
.exit();
|
||||
});
|
||||
trace!("SubDirectory arguments: path: {:?}", path);
|
||||
// Nightly feature std::path::absolute
|
||||
let path = path.canonicalize()?;
|
||||
trace!("canonicalized: path: {:?}", path);
|
||||
|
||||
let key_name = ask_unique_name(&storages, "sub-directory".to_string())?;
|
||||
let notes = Text::new("Notes for this sub-directory:").prompt()?;
|
||||
let storage = storages::directory::Directory::try_from_device_path(
|
||||
key_name.clone(),
|
||||
path,
|
||||
notes,
|
||||
&device,
|
||||
&storages,
|
||||
)?;
|
||||
(key_name, Storage::SubDirectory(storage))
|
||||
}
|
||||
StorageType::Online => {
|
||||
let path = path.unwrap_or_else(|| {
|
||||
let mut cmd = Cli::command();
|
||||
cmd.error(
|
||||
ErrorKind::MissingRequiredArgument,
|
||||
"<PATH> is required with sub-directory",
|
||||
)
|
||||
.exit();
|
||||
});
|
||||
let mut name = String::new();
|
||||
loop {
|
||||
name = Text::new("Name for the storage:")
|
||||
.with_validator(min_length!(0, "At least 1 character"))
|
||||
.prompt()
|
||||
.context("Failed to get Name")?;
|
||||
if storages.iter().all(|(k, _v)| k != &name) {
|
||||
break;
|
||||
}
|
||||
println!("The name {} is already used.", name);
|
||||
}
|
||||
let provider = Text::new("Provider:")
|
||||
.prompt()
|
||||
.context("Failed to get provider")?;
|
||||
let capacity: u64 = CustomType::<u64>::new("Capacity (byte):")
|
||||
.with_error_message("Please type number.")
|
||||
.prompt()
|
||||
.context("Failed to get capacity.")?;
|
||||
let alias = Text::new("Alias:")
|
||||
.prompt()
|
||||
.context("Failed to get provider")?;
|
||||
let storage = OnlineStorage::new(
|
||||
name.clone(),
|
||||
provider,
|
||||
capacity,
|
||||
alias,
|
||||
path,
|
||||
&device,
|
||||
);
|
||||
(name, Storage::Online(storage))
|
||||
}
|
||||
};
|
||||
|
||||
// add to storages
|
||||
storages.insert(key.clone(), storage);
|
||||
trace!("updated storages: {:?}", storages);
|
||||
|
||||
// write to file
|
||||
write_storages(&config_dir, storages)?;
|
||||
|
||||
// commit
|
||||
add_and_commit(
|
||||
&repo,
|
||||
&Path::new(STORAGESFILE),
|
||||
&format!("Add new storage(physical drive): {}", key),
|
||||
)?;
|
||||
|
||||
println!("Added new storage.");
|
||||
trace!("Finished adding storage");
|
||||
}
|
||||
StorageCommands::List {} => {
|
||||
// Get storages
|
||||
let storages: HashMap<String, Storage> = get_storages(&config_dir)?;
|
||||
trace!("found storages: {:?}", storages);
|
||||
let device = get_device(&config_dir)?;
|
||||
for (k, storage) in &storages {
|
||||
println!("{}: {}", k, storage);
|
||||
println!(" {}", storage.mount_path(&device, &storages)?.display());
|
||||
// println!("{}: {}", storage.shorttypename(), storage.name()); // TODO
|
||||
}
|
||||
cmd_storage::cmd_storage_add(storage_type, path, repo, &config_dir)?
|
||||
}
|
||||
StorageCommands::List {} => cmd_storage::cmd_storage_list(&config_dir)?,
|
||||
StorageCommands::Bind {
|
||||
storage: storage_name,
|
||||
alias: new_alias,
|
||||
path: mount_point,
|
||||
} => {
|
||||
let device = get_device(&config_dir)?;
|
||||
// get storages
|
||||
let mut storages: HashMap<String, Storage> = get_storages(&config_dir)?;
|
||||
let commit_comment = {
|
||||
// find matching storage
|
||||
let storage = &mut storages
|
||||
.get_mut(&storage_name)
|
||||
.context(format!("No storage has name {}", storage_name))?;
|
||||
let old_alias = storage
|
||||
.local_info(&device)
|
||||
.context(format!("Failed to get LocalInfo for {}", storage.name()))?
|
||||
.alias()
|
||||
.clone();
|
||||
// TODO: get mount path for directory automatically?
|
||||
storage.bound_on_device(new_alias, mount_point, &device)?;
|
||||
// trace!("storage: {}", &storage);
|
||||
format!("{} to {}", old_alias, storage.name())
|
||||
};
|
||||
trace!("bound new system name to the storage");
|
||||
trace!("storages: {:#?}", storages);
|
||||
|
||||
write_storages(&config_dir, storages)?;
|
||||
// commit
|
||||
add_and_commit(
|
||||
&repo,
|
||||
&Path::new(STORAGESFILE),
|
||||
&format!(
|
||||
"Bound new storage name to physical drive ({})",
|
||||
commit_comment
|
||||
),
|
||||
)?;
|
||||
println!(
|
||||
"Bound new storage name to physical drive ({})",
|
||||
commit_comment
|
||||
);
|
||||
}
|
||||
} => cmd_storage::cmd_storage_bind(
|
||||
storage_name,
|
||||
new_alias,
|
||||
mount_point,
|
||||
repo,
|
||||
&config_dir,
|
||||
)?,
|
||||
}
|
||||
}
|
||||
Commands::Path {} => {
|
||||
|
|
Loading…
Reference in a new issue