use anyhow::Result;
use std::path::PathBuf;
use thiserror::Error;
#[derive(Debug, Default)]
pub struct ProjectIndex {
entries: Vec<ProjectEntry>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProjectEntry {
pub absolute_path: PathBuf,
pub basename_slug: String,
pub session_archive_paths: Vec<PathBuf>,
}
impl ProjectIndex {
pub fn open() -> Result<Self> {
Err(IndexError::NotImplemented { method: "open" }.into())
}
pub fn rebuild_from_manifests(&mut self) -> Result<()> {
Err(IndexError::NotImplemented {
method: "rebuild_from_manifests",
}
.into())
}
pub fn lookup(&self, _query: &str) -> Result<ProjectEntry> {
Err(IndexError::NotImplemented { method: "lookup" }.into())
}
pub fn is_stale(&self) -> Result<bool> {
Err(IndexError::NotImplemented { method: "is_stale" }.into())
}
pub fn entry_count(&self) -> usize {
self.entries.len()
}
}
#[derive(Debug, Error)]
pub enum IndexError {
#[error("ambiguous project query '{query}' matches multiple paths: {matches:?}")]
AmbiguousProject {
query: String,
matches: Vec<PathBuf>,
},
#[error("ProjectIndex::{method} is not yet implemented (wired up in a later PR)")]
NotImplemented { method: &'static str },
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn project_index_default_is_empty() {
let idx = ProjectIndex::default();
assert_eq!(idx.entry_count(), 0);
}
#[test]
fn project_entry_constructable() {
let entry = ProjectEntry {
absolute_path: PathBuf::from("/home/charlie/recipes/coryzibell/mx"),
basename_slug: "mx".to_string(),
session_archive_paths: vec![PathBuf::from(
"/home/charlie/.wonka/codex/2026-04-29-143022-c3744b8d",
)],
};
assert_eq!(entry.basename_slug, "mx");
assert_eq!(entry.session_archive_paths.len(), 1);
}
#[test]
fn index_error_ambiguous_renders_query_and_matches() {
let err = IndexError::AmbiguousProject {
query: "mx".to_string(),
matches: vec![PathBuf::from("/home/a/mx"), PathBuf::from("/home/b/mx")],
};
let msg = format!("{}", err);
assert!(msg.contains("'mx'"), "rendered message: {}", msg);
assert!(msg.contains("/home/a/mx"), "rendered message: {}", msg);
assert!(msg.contains("/home/b/mx"), "rendered message: {}", msg);
}
}