use anyhow::{Context, Result};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::{Path, PathBuf};
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
#[serde(default, deny_unknown_fields)]
pub struct RepoTrust {
pub allow_project_commands: bool,
pub trusted_at: Option<DateTime<Utc>>,
}
impl RepoTrust {
pub fn is_trusted(&self) -> bool {
self.allow_project_commands
}
}
pub fn project_trust_path(repo_root: &Path) -> PathBuf {
repo_root.join(".ralph").join("trust.jsonc")
}
pub fn load_repo_trust(repo_root: &Path) -> Result<RepoTrust> {
let path = project_trust_path(repo_root);
if !path.exists() {
return Ok(RepoTrust::default());
}
let raw = fs::read_to_string(&path).with_context(|| format!("read {}", path.display()))?;
crate::jsonc::parse_jsonc::<RepoTrust>(&raw, &format!("trust {}", path.display()))
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::TempDir;
#[test]
fn project_trust_path_is_jsonc_only() {
let repo_root = TempDir::new().expect("temp dir");
assert_eq!(
project_trust_path(repo_root.path()),
repo_root.path().join(".ralph/trust.jsonc")
);
}
#[test]
fn load_repo_trust_ignores_legacy_json_file() {
let repo_root = TempDir::new().expect("temp dir");
let ralph_dir = repo_root.path().join(".ralph");
fs::create_dir_all(&ralph_dir).expect("create .ralph");
fs::write(
ralph_dir.join("trust.json"),
r#"{"allow_project_commands":true}"#,
)
.expect("write legacy trust file");
assert_eq!(
load_repo_trust(repo_root.path()).expect("load trust"),
RepoTrust::default()
);
}
}