use std::io::{self, Write};
use std::path::Path;
use tracing::info;
use crate::config::{Config, DEFAULT_PROJECT_CONFIG, DEFAULT_PROMPTS};
use crate::error::{Error, Result};
use crate::project::{PROMPTS_FILE_DEFAULT, ProjectLayout};
use crate::store::Store;
pub fn run(path: &Path, force: bool) -> Result<()> {
let layout = ProjectLayout::new(path);
if path.exists() {
let confirmed = if force {
true
} else {
confirm_overwrite(path)?
};
if !confirmed {
return Err(Error::Store(format!(
"init aborted — `{}` left untouched",
path.display()
)));
}
if let Ok(cwd) = std::env::current_dir() {
if let Ok(abs_target) = std::fs::canonicalize(path) {
if cwd.starts_with(&abs_target) {
return Err(Error::Store(format!(
"refusing to wipe `{}` — your current directory lives inside it",
abs_target.display()
)));
}
}
}
std::fs::remove_dir_all(path).map_err(Error::Io)?;
}
layout.create_layout()?;
let config_path = layout.config_path();
std::fs::write(&config_path, DEFAULT_PROJECT_CONFIG)?;
info!(path = %config_path.display(), "wrote project config");
let prompts_path = layout.root.join(PROMPTS_FILE_DEFAULT);
std::fs::write(&prompts_path, DEFAULT_PROMPTS)?;
info!(path = %prompts_path.display(), "wrote prompt library");
let cfg = Config::load(&config_path)?;
let _store = Store::open(layout.clone(), &cfg)?;
eprintln!("Initialized inkhaven project at {}", layout.root.display());
eprintln!(" config: {}", layout.config_path().display());
eprintln!(" prompts: {}", layout.root.join(PROMPTS_FILE_DEFAULT).display());
eprintln!(" store db: {}", layout.metadata_db_path().display());
eprintln!(" vecstore: {}", layout.vecstore_path().display());
eprintln!(" books: {}", layout.books_path().display());
Ok(())
}
fn confirm_overwrite(path: &Path) -> Result<bool> {
eprint!(
"Directory `{}` already exists. Remove it and re-initialise? [y/N] ",
path.display()
);
io::stderr().flush().ok();
let mut buf = String::new();
if io::stdin().read_line(&mut buf).map_err(Error::Io)? == 0 {
return Ok(false);
}
let answer = buf.trim().to_ascii_lowercase();
Ok(matches!(answer.as_str(), "y" | "yes"))
}