use anyhow::{Context, Result};
use std::path::{Path, PathBuf};
include!(concat!(env!("OUT_DIR"), "/prompts_generated.rs"));
const COMPLETE_MARKER: &str = ".sashiko-prompts-complete";
pub fn default_kernel_prompts_path() -> Result<PathBuf> {
let root = install_prompt_bundle(false)?;
Ok(root.join("kernel"))
}
pub fn install_prompt_bundle(force: bool) -> Result<PathBuf> {
let root = prompt_bundle_root()?;
let marker = root.join(COMPLETE_MARKER);
if !force && marker.exists() {
return Ok(root);
}
if force && root.exists() {
std::fs::remove_dir_all(&root)
.with_context(|| format!("failed to remove {}", root.display()))?;
}
for (relative, content) in PROMPT_BUNDLE_FILES {
let path = root.join(relative);
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)
.with_context(|| format!("failed to create {}", parent.display()))?;
}
std::fs::write(&path, content)
.with_context(|| format!("failed to write {}", path.display()))?;
}
std::fs::write(&marker, PROMPT_BUNDLE_REVISION)
.with_context(|| format!("failed to write {}", marker.display()))?;
Ok(root)
}
pub fn prompt_bundle_root() -> Result<PathBuf> {
Ok(data_home()?
.join("sashiko/prompts")
.join(PROMPT_BUNDLE_REVISION))
}
fn data_home() -> Result<PathBuf> {
if let Some(data_home) = std::env::var_os("XDG_DATA_HOME") {
return Ok(PathBuf::from(data_home));
}
if let Some(home) = std::env::var_os("HOME") {
return Ok(Path::new(&home).join(".local/share"));
}
Ok(std::env::current_dir()?.join(".local/share"))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_prompt_bundle_contains_kernel_review_core() {
assert!(
PROMPT_BUNDLE_FILES
.iter()
.any(|(path, _)| *path == "kernel/review-core.md")
);
}
#[test]
fn test_prompt_bundle_root_uses_xdg_data_home() {
let temp = tempfile::tempdir().unwrap();
let old_xdg = std::env::var_os("XDG_DATA_HOME");
unsafe {
std::env::set_var("XDG_DATA_HOME", temp.path());
}
assert_eq!(
prompt_bundle_root().unwrap(),
temp.path()
.join("sashiko/prompts")
.join(PROMPT_BUNDLE_REVISION)
);
unsafe {
if let Some(value) = old_xdg {
std::env::set_var("XDG_DATA_HOME", value);
} else {
std::env::remove_var("XDG_DATA_HOME");
}
}
}
}