Skip to main content

llm_wiki/ops/
history.rs

1use anyhow::Result;
2use serde::{Deserialize, Serialize};
3
4use crate::engine::EngineState;
5use crate::git;
6use crate::slug::{Slug, WikiUri};
7
8/// Git history for a single page — slug and log entries.
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct HistoryResult {
11    /// Slug of the page whose history was fetched.
12    pub slug: String,
13    /// Ordered list of git commit entries (most recent first).
14    pub entries: Vec<git::HistoryEntry>,
15}
16
17/// Return git commit history for a page slug or `wiki://` URI.
18pub fn history(
19    engine: &EngineState,
20    slug_or_uri: &str,
21    wiki_flag: Option<&str>,
22    limit: Option<usize>,
23    follow: Option<bool>,
24) -> Result<HistoryResult> {
25    let (wiki_name, slug) = if slug_or_uri.starts_with("wiki://") {
26        let (entry, slug) = WikiUri::resolve(slug_or_uri, wiki_flag, &engine.config)?;
27        (entry.name, slug)
28    } else {
29        let wiki_name = engine.resolve_wiki_name(wiki_flag).to_string();
30        let slug = Slug::try_from(slug_or_uri)?;
31        (wiki_name, slug)
32    };
33
34    let space = engine.space(&wiki_name)?;
35    let resolved = space.resolved_config(&engine.config);
36
37    let limit = limit.unwrap_or(resolved.history.default_limit as usize);
38    let follow = follow.unwrap_or(resolved.history.follow);
39
40    // Resolve slug to absolute path, then make relative to repo root
41    let abs_path = slug.resolve(&space.wiki_root)?;
42    let rel_path = abs_path.strip_prefix(&space.repo_root).unwrap_or(&abs_path);
43
44    let entries = git::page_history(&space.repo_root, rel_path, limit, follow)?;
45
46    Ok(HistoryResult {
47        slug: slug.to_string(),
48        entries,
49    })
50}