use crate::provider::{
FieldSchema, FieldType, InvalidationStrategy, Provider, ProviderMetadata, ProviderResult, Value,
};
use std::path::Path;
use std::process::Command;
pub struct DirenvProvider;
impl Provider for DirenvProvider {
fn metadata(&self) -> ProviderMetadata {
ProviderMetadata {
name: "direnv".to_string(),
fields: vec![
FieldSchema {
name: "status".to_string(),
field_type: FieldType::String,
},
FieldSchema {
name: "allowed".to_string(),
field_type: FieldType::Bool,
},
],
invalidation: InvalidationStrategy::Watch {
patterns: vec![".envrc".to_string()],
fallback_poll_secs: Some(30),
},
global: false,
}
}
fn execute(&self, path: Option<&str>) -> Option<ProviderResult> {
let path = path?;
let dir = Path::new(path);
if !dir.join(".envrc").exists() {
return None;
}
let allowed = Command::new("direnv")
.args(["status"])
.current_dir(dir)
.output()
.ok()
.map(|o| {
let stdout = String::from_utf8_lossy(&o.stdout);
stdout.contains("Found RC allowed true")
})
.unwrap_or(false);
let status = if allowed { "loaded" } else { "blocked" };
let mut result = ProviderResult::new();
result.insert("status", Value::String(status.to_string()));
result.insert("allowed", Value::Bool(allowed));
Some(result)
}
}