fur_cli/commands/
rebuild.rs1use std::path::Path;
2
3use clap::Parser;
4use colored::*;
5
6use crate::schema::rebuild::{detect_state, rebuild, ProjectState, RebuildSummary};
7
8#[derive(Parser, Debug)]
10pub struct RebuildArgs {
11 #[arg(long)]
13 pub force: bool,
14}
15
16pub fn run_rebuild(args: RebuildArgs) {
18 let root = Path::new(".");
19
20 match detect_state(root) {
21 ProjectState::Locked => {
22 println!("🔒 Archive is locked. Run `fur unlock` first.");
23 return;
24 }
25 ProjectState::Empty => {
26 println!("📭 No conversation documents found under chats/.");
27 println!(" Run `fur new \"Title\"` to start a diary.");
28 return;
29 }
30 _ => {}
31 }
32
33 match rebuild(root, args.force) {
34 Ok(summary) => report(&summary),
35 Err(e) => eprintln!("❌ {}", e),
36 }
37}
38
39pub fn preflight(exempt: bool) -> bool {
46 let root = Path::new(".");
47
48 match detect_state(root) {
49 ProjectState::Locked if !exempt => {
50 println!(
51 "{}",
52 "🔒 This project is locked.".bright_yellow().bold()
53 );
54 println!("{}", " Run `fur unlock` to read it.".bright_black());
55 false
56 }
57 ProjectState::Unindexed if !exempt => {
58 auto_rebuild_if_needed();
59 true
60 }
61 _ => true,
62 }
63}
64
65pub fn auto_rebuild_if_needed() {
69 let root = Path::new(".");
70
71 if detect_state(root) != ProjectState::Unindexed {
72 return;
73 }
74
75 println!(
76 "{}",
77 "📦 Conversation documents found, but no .fur/ index."
78 .bright_yellow()
79 .bold()
80 );
81 println!("{}", " Rebuilding from chats/...".bright_black());
82
83 match rebuild(root, false) {
84 Ok(summary) => report(&summary),
85 Err(e) => eprintln!("❌ Rebuild failed: {}", e),
86 }
87}
88
89fn report(summary: &RebuildSummary) {
90 println!(
91 "{}",
92 format!(
93 "✔ Rebuilt {} conversation(s), {} message(s).",
94 summary.conversations, summary.messages
95 )
96 .bright_green()
97 .bold()
98 );
99
100 if !summary.skipped.is_empty() {
101 println!("\n{}", "Skipped documents".bold().truecolor(255, 105, 180));
102 for s in &summary.skipped {
103 println!(" ✖ {}", s.truecolor(255, 105, 180));
104 }
105 }
106
107 if !summary.avatars.is_empty() {
108 println!(
109 "\n{} {}",
110 "Avatars found:".bright_cyan().bold(),
111 summary.avatars.join(", ").bright_white().bold()
112 );
113 }
114
115 if let Some(main) = &summary.guessed_main {
119 println!(
120 "{}",
121 format!(" Assuming \"{}\" is you.", main)
122 .bright_yellow()
123 .bold()
124 );
125 }
126
127 println!(
128 "{}",
129 " → Run `fur onboard` to confirm that and pick faces."
130 .bright_magenta()
131 .bold()
132 );
133}