context: add context
All checks were successful
CI / build (push) Successful in 1m50s

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:
2025-12-15 20:48:44 +01:00
parent ad98d9c1ab
commit 1d65d1ce31
9 changed files with 789 additions and 12 deletions

88
src/context/mod.rs Normal file
View File

@@ -0,0 +1,88 @@
mod api;
mod local;
mod manager;
mod ssh;
pub use api::{CommandRunner, Context, ContextCommand};
pub use manager::ContextManager;
pub fn current_context() -> Context {
match ContextManager::new() {
Ok(mgr) => mgr.current(),
Err(_) => Context::Local,
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
use tempfile::NamedTempFile;
#[test]
fn test_ensure_available_local() {
let temp_dir = tempfile::tempdir().unwrap();
let src_file = temp_dir.path().join("src.txt");
fs::write(&src_file, "local").unwrap();
let ctx = Context::Local;
let dest = ctx.ensure_available(&src_file, "/tmp").unwrap();
// Should return canonical path
assert_eq!(dest, src_file.canonicalize().unwrap());
}
#[test]
fn test_context_manager_crud() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path().to_path_buf();
let mut mgr = ContextManager::with_path(path.clone());
// Add
let ssh_ctx = Context::Ssh {
host: "10.0.0.1".into(),
user: Some("admin".into()),
port: Some(2222),
};
mgr.add_context("myserver", ssh_ctx.clone()).unwrap();
assert!(mgr.get_context("myserver").is_some());
assert_eq!(mgr.get_context("myserver").unwrap(), &ssh_ctx);
// List
let list = mgr.list_contexts();
assert!(list.contains(&"myserver".to_string()));
// Set Current
mgr.set_current("myserver").unwrap();
assert_eq!(mgr.current(), ssh_ctx);
assert_eq!(mgr.current_name(), Some("myserver".to_string()));
// Remove
mgr.remove_context("myserver").unwrap();
assert!(mgr.get_context("myserver").is_none());
assert_eq!(mgr.current(), Context::Local);
}
#[test]
fn test_persistence() {
let temp_dir = tempfile::tempdir().unwrap();
let config_path = temp_dir.path().join("contexts.json");
{
let mut mgr = ContextManager::with_path(config_path.clone());
mgr.add_context("persistent", Context::Local).unwrap();
mgr.set_current("persistent").unwrap();
}
let content = fs::read_to_string(&config_path).unwrap();
let loaded_config: super::manager::Config = serde_json::from_str(&content).unwrap();
assert_eq!(
loaded_config.current_context,
Some("persistent".to_string())
);
assert!(loaded_config.contexts.contains_key("persistent"));
}
}