pkh context allows to manage contexts (local, ssh) and run contextualized commands (deb) in other words, this allows building binary packages over ssh
This commit is contained in:
117
src/context/manager.rs
Normal file
117
src/context/manager.rs
Normal file
@@ -0,0 +1,117 @@
|
||||
use directories::ProjectDirs;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::api::Context;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Default, Clone)]
|
||||
pub struct Config {
|
||||
pub current_context: Option<String>,
|
||||
pub contexts: HashMap<String, Context>,
|
||||
}
|
||||
|
||||
pub struct ContextManager {
|
||||
config_path: PathBuf,
|
||||
config: Config,
|
||||
}
|
||||
|
||||
impl ContextManager {
|
||||
pub fn new() -> io::Result<Self> {
|
||||
let proj_dirs = ProjectDirs::from("com", "pkh", "pkh").ok_or_else(|| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::NotFound,
|
||||
"Could not determine config directory",
|
||||
)
|
||||
})?;
|
||||
let config_dir = proj_dirs.config_dir();
|
||||
fs::create_dir_all(config_dir)?;
|
||||
let config_path = config_dir.join("contexts.json");
|
||||
|
||||
let config = if config_path.exists() {
|
||||
let content = fs::read_to_string(&config_path)?;
|
||||
serde_json::from_str(&content)
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?
|
||||
} else {
|
||||
let mut cfg = Config::default();
|
||||
cfg.contexts.insert("local".to_string(), Context::Local);
|
||||
cfg.current_context = Some("local".to_string());
|
||||
cfg
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
config_path,
|
||||
config,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn with_path(path: PathBuf) -> Self {
|
||||
Self {
|
||||
config_path: path,
|
||||
config: Config::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save(&self) -> io::Result<()> {
|
||||
let content = serde_json::to_string_pretty(&self.config)
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||
fs::write(&self.config_path, content)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn list_contexts(&self) -> Vec<String> {
|
||||
self.config.contexts.keys().cloned().collect()
|
||||
}
|
||||
|
||||
pub fn get_context(&self, name: &str) -> Option<&Context> {
|
||||
self.config.contexts.get(name)
|
||||
}
|
||||
|
||||
pub fn add_context(&mut self, name: &str, context: Context) -> io::Result<()> {
|
||||
self.config.contexts.insert(name.to_string(), context);
|
||||
self.save()
|
||||
}
|
||||
|
||||
pub fn remove_context(&mut self, name: &str) -> io::Result<()> {
|
||||
if self.config.contexts.remove(name).is_some() {
|
||||
if self.config.current_context.as_deref() == Some(name) {
|
||||
self.config.current_context = Some("local".to_string());
|
||||
if !self.config.contexts.contains_key("local") {
|
||||
self.config
|
||||
.contexts
|
||||
.insert("local".to_string(), Context::Local);
|
||||
}
|
||||
}
|
||||
self.save()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_current(&mut self, name: &str) -> io::Result<()> {
|
||||
if self.config.contexts.contains_key(name) {
|
||||
self.config.current_context = Some(name.to_string());
|
||||
self.save()?;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::NotFound,
|
||||
format!("Context '{}' not found", name),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current(&self) -> Context {
|
||||
self.config
|
||||
.current_context
|
||||
.as_deref()
|
||||
.and_then(|name| self.config.contexts.get(name))
|
||||
.cloned()
|
||||
.unwrap_or(Context::Local)
|
||||
}
|
||||
|
||||
pub fn current_name(&self) -> Option<String> {
|
||||
self.config.current_context.clone()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user