1use std::collections::HashMap;
2
3use libgrite_core::{
4 config::list_actors,
5 integrity::{check_store_integrity, verify_store_signatures, CorruptionKind},
6 types::ids::id_to_hex,
7 GriteError,
8};
9
10use crate::context::GriteContext;
11use crate::types::*;
12
13pub fn db_stats(ctx: &GriteContext) -> Result<DbStatsResult, GriteError> {
15 let store = ctx.open_store()?;
16 let sled_path = ctx.sled_path();
17
18 let stats = store.stats(&sled_path)?;
19
20 Ok(DbStatsResult {
21 path: sled_path,
22 size_bytes: stats.size_bytes,
23 event_count: stats.event_count,
24 issue_count: stats.issue_count,
25 last_rebuild_ts: stats.last_rebuild_ts,
26 events_since_rebuild: stats.events_since_rebuild,
27 days_since_rebuild: stats.days_since_rebuild,
28 rebuild_recommended: stats.rebuild_recommended,
29 })
30}
31
32pub fn db_check(ctx: &GriteContext, opts: &DbCheckOptions) -> Result<DbCheckResult, GriteError> {
34 let store = ctx.open_store()?;
35
36 let report = check_store_integrity(&store, opts.verify_parents)?;
37
38 let hash_mismatches: Vec<String> = report
39 .corrupt_events
40 .iter()
41 .filter_map(|e| {
42 if let CorruptionKind::HashMismatch { expected, computed } = &e.kind {
43 Some(format!(
44 "{}: hash mismatch expected {} computed {}",
45 id_to_hex(&e.event_id),
46 id_to_hex(expected),
47 id_to_hex(computed)
48 ))
49 } else {
50 None
51 }
52 })
53 .collect();
54
55 let parent_errors: Vec<String> = report
56 .corrupt_events
57 .iter()
58 .filter_map(|e| {
59 if let CorruptionKind::MissingParent { parent_id } = &e.kind {
60 Some(format!(
61 "{}: missing parent {}",
62 id_to_hex(&e.event_id),
63 id_to_hex(parent_id)
64 ))
65 } else {
66 None
67 }
68 })
69 .collect();
70
71 Ok(DbCheckResult {
72 checked_events: report.events_checked,
73 hash_mismatches,
74 parent_errors,
75 })
76}
77
78pub fn db_verify(
80 ctx: &GriteContext,
81 _opts: &DbVerifyOptions,
82) -> Result<DbVerifyResult, GriteError> {
83 let store = ctx.open_store()?;
84
85 let actors = list_actors(&ctx.git_dir)?;
86 let mut public_keys: HashMap<String, String> = HashMap::new();
87
88 for actor in &actors {
89 if let Some(pk) = &actor.public_key {
90 public_keys.insert(actor.actor_id.clone(), pk.clone());
91 }
92 }
93
94 let get_public_key = |actor_id: &str| -> Option<String> { public_keys.get(actor_id).cloned() };
95
96 let report = verify_store_signatures(&store, get_public_key)?;
97
98 let invalid_signatures: Vec<String> = report
99 .signature_errors
100 .iter()
101 .map(|e| {
102 format!(
103 "{} (actor {}): {}",
104 id_to_hex(&e.event_id),
105 e.actor_id,
106 e.error
107 )
108 })
109 .collect();
110
111 Ok(DbVerifyResult {
112 checked_events: report.events_checked,
113 invalid_signatures,
114 })
115}