use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use crate::error::{GwmError, Result};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TrustedRepo {
pub config_path: PathBuf,
pub config_hash: String,
pub trusted_at: String,
pub trusted_commands: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TrustCache {
pub version: u8,
pub repos: HashMap<String, TrustedRepo>,
}
impl Default for TrustCache {
fn default() -> Self {
Self {
version: 1,
repos: HashMap::new(),
}
}
}
pub fn normalize_repo_path(path: &Path) -> Result<String> {
let canonical = path.canonicalize().map_err(|e| {
GwmError::path(format!(
"Failed to canonicalize repository path '{}': {}",
path.display(),
e
))
})?;
Ok(canonical.to_string_lossy().to_string())
}
pub fn normalize_repo_path_or_display(path: &Path) -> String {
normalize_repo_path(path).unwrap_or_else(|_| path.display().to_string())
}
#[derive(Debug, Clone)]
pub enum TrustStatus {
Trusted,
GlobalConfig,
NoHooks,
NeedsConfirmation {
reason: ConfirmationReason,
commands: Vec<String>,
config_path: PathBuf,
config_hash: String,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConfirmationReason {
FirstTime,
ConfigChanged,
}
impl ConfirmationReason {
pub fn description(&self) -> &'static str {
match self {
Self::FirstTime => "First time running hooks for this project",
Self::ConfigChanged => "Project hook configuration has changed",
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_trust_cache_default() {
let cache = TrustCache::default();
assert_eq!(cache.version, 1);
assert!(cache.repos.is_empty());
}
#[test]
fn test_confirmation_reason_description() {
assert_eq!(
ConfirmationReason::FirstTime.description(),
"First time running hooks for this project"
);
assert_eq!(
ConfirmationReason::ConfigChanged.description(),
"Project hook configuration has changed"
);
}
#[test]
fn test_trust_cache_serialization() {
let mut cache = TrustCache::default();
cache.repos.insert(
"/path/to/repo".to_string(),
TrustedRepo {
config_path: PathBuf::from("/path/to/repo/.gwm/config.toml"),
config_hash: "abc123".to_string(),
trusted_at: "2024-01-01T00:00:00Z".to_string(),
trusted_commands: vec!["npm install".to_string()],
},
);
let json = serde_json::to_string(&cache).unwrap();
let parsed: TrustCache = serde_json::from_str(&json).unwrap();
assert_eq!(parsed.version, 1);
assert!(parsed.repos.contains_key("/path/to/repo"));
}
}