1pub mod git;
9pub mod stale;
10pub mod duplicates;
11
12use serde::{Deserialize, Serialize};
13use std::path::PathBuf;
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct Recommendation {
18 pub kind: RecommendationKind,
20 pub title: String,
22 pub description: String,
24 pub path: PathBuf,
26 pub potential_savings: u64,
28 pub fix_command: Option<String>,
30 pub risk: RiskLevel,
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
36pub enum RecommendationKind {
37 GitOptimization,
39 GitLfsCache,
41 StaleProject,
43 DuplicateDependency,
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
49pub enum RiskLevel {
50 None,
52 Low,
54 Medium,
56 High,
58}
59
60impl RiskLevel {
61 pub fn color_hint(&self) -> &'static str {
63 match self {
64 Self::None => "green",
65 Self::Low => "blue",
66 Self::Medium => "yellow",
67 Self::High => "red",
68 }
69 }
70
71 pub fn symbol(&self) -> &'static str {
73 match self {
74 Self::None => "✓",
75 Self::Low => "○",
76 Self::Medium => "~",
77 Self::High => "!",
78 }
79 }
80}
81
82impl Recommendation {
83 pub fn savings_display(&self) -> String {
85 format_size(self.potential_savings)
86 }
87}
88
89pub fn format_size(bytes: u64) -> String {
91 const KB: u64 = 1024;
92 const MB: u64 = KB * 1024;
93 const GB: u64 = MB * 1024;
94
95 if bytes >= GB {
96 format!("{:.2} GiB", bytes as f64 / GB as f64)
97 } else if bytes >= MB {
98 format!("{:.2} MiB", bytes as f64 / MB as f64)
99 } else if bytes >= KB {
100 format!("{:.2} KiB", bytes as f64 / KB as f64)
101 } else {
102 format!("{} B", bytes)
103 }
104}