129 lines
3.7 KiB
Rust
129 lines
3.7 KiB
Rust
use anyhow::Result;
|
|
use colored::Colorize;
|
|
use crate::{ platform::Platform, input };
|
|
use flexbuffers::{ FlexbufferSerializer, Reader };
|
|
use std::collections::BTreeSet;
|
|
use std::fs;
|
|
use std::path;
|
|
use serde::{ Serialize, Deserialize };
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
|
pub struct Host {
|
|
pub platform: Platform,
|
|
pub id: String,
|
|
pub user: String,
|
|
pub host: String,
|
|
pub port: i16,
|
|
pub config: String
|
|
}
|
|
|
|
impl std::fmt::Display for Host {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
f.write_fmt(std::format_args!("[{}] {}@{}", self.platform, self.user, self.host))
|
|
}
|
|
}
|
|
|
|
impl Host {
|
|
pub fn edit(&mut self, config: &mut ConfigManager) -> Result<Self> {
|
|
let data = toml::to_string_pretty(self)?;
|
|
let t = input::edit_temp_from_string(&data)?;
|
|
|
|
match toml::from_str::<Self>(&fs::read_to_string(t)?) {
|
|
Ok(d) => {
|
|
println!(" ## {} ## ", "Definition OK".green());
|
|
|
|
// Replace old config with new config
|
|
config.configs.remove(self);
|
|
config.configs.insert(d.to_owned());
|
|
config.save();
|
|
|
|
Ok(d)
|
|
},
|
|
Err(e) => {
|
|
println!(" ## {}: {} ## ", "Rejecting definition".red(), e);
|
|
Ok(self.to_owned())
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
|
pub struct ConfigManager {
|
|
#[serde(skip)]
|
|
pub config_dir: path::PathBuf,
|
|
#[serde(skip)]
|
|
pub search_path: path::PathBuf,
|
|
pub configs: BTreeSet<Host>,
|
|
}
|
|
|
|
|
|
impl ConfigManager {
|
|
pub fn new(given_config_root: Option<String>, search_path: Option<String>) -> Result<Self> {
|
|
// Resolve config root
|
|
let config_root = match given_config_root {
|
|
Some(c) => path::Path::new(&c).to_owned(),
|
|
None => dirs::data_local_dir().unwrap().join("keyman/"),
|
|
};
|
|
|
|
// Make config root if it doesn't exist (eg: first run)
|
|
if !fs::try_exists(config_root.to_owned()).unwrap_or(false) {
|
|
fs::create_dir_all(config_root.to_owned())?;
|
|
}
|
|
|
|
// Resolve search path
|
|
let search_path = match search_path {
|
|
Some(s) => std::path::Path::new(&s).to_owned(),
|
|
None => dirs::home_dir().unwrap().join(".ssh/"),
|
|
};
|
|
|
|
// Read config
|
|
let config = fs::read(config_root.join("config"));
|
|
if config.is_err() {
|
|
return Ok(Self { config_dir: config_root.to_owned(), search_path, configs: BTreeSet::new() })
|
|
}
|
|
let config = config.unwrap();
|
|
|
|
// Deserialize
|
|
let root = Reader::get_root(config.as_slice())?;
|
|
let mgr = ConfigManager::deserialize(root);
|
|
|
|
if mgr.is_err() {
|
|
return Ok(Self { config_dir: config_root, search_path, configs: BTreeSet::new() })
|
|
}
|
|
|
|
let mgr = mgr.unwrap();
|
|
Ok(Self { config_dir: config_root, search_path, configs: mgr.configs.to_owned() })
|
|
}
|
|
|
|
pub fn remove(&mut self, host: &Host) {
|
|
self.configs.remove(host);
|
|
self.save();
|
|
}
|
|
|
|
pub fn insert(&mut self, host: Host) {
|
|
self.configs.insert(host);
|
|
self.save();
|
|
}
|
|
|
|
pub fn save(&mut self) {
|
|
let mut s = FlexbufferSerializer::new();
|
|
self.serialize(&mut s).unwrap();
|
|
fs::write(self.config_dir.to_owned().join("config"), s.view()).unwrap();
|
|
}
|
|
|
|
pub fn new_host(&mut self) -> Result<Host> {
|
|
let platform = input::get_platform()?;
|
|
let host = platform.new_host(self)?;
|
|
self.configs.insert(host.to_owned());
|
|
self.save();
|
|
Ok(host)
|
|
}
|
|
}
|
|
|
|
impl Drop for ConfigManager {
|
|
fn drop(&mut self) {
|
|
self.save();
|
|
}
|
|
} |