Skip to main content

null_e/analysis/
mod.rs

1//! Analysis modules for deeper codebase insights
2//!
3//! This module contains analysis tools that go beyond simple cleanup:
4//! - Git repository health and optimization
5//! - Stale project detection
6//! - Duplicate dependency detection
7
8pub mod git;
9pub mod stale;
10pub mod duplicates;
11
12use serde::{Deserialize, Serialize};
13use std::path::PathBuf;
14
15/// A recommendation from analysis
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct Recommendation {
18    /// Type of recommendation
19    pub kind: RecommendationKind,
20    /// Human-readable title
21    pub title: String,
22    /// Detailed description
23    pub description: String,
24    /// Affected path
25    pub path: PathBuf,
26    /// Potential space savings in bytes
27    pub potential_savings: u64,
28    /// Command to fix (if applicable)
29    pub fix_command: Option<String>,
30    /// Risk level
31    pub risk: RiskLevel,
32}
33
34/// Types of recommendations
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
36pub enum RecommendationKind {
37    /// Git repository optimization
38    GitOptimization,
39    /// Git LFS cache cleanup
40    GitLfsCache,
41    /// Stale project that hasn't been touched
42    StaleProject,
43    /// Duplicate dependencies
44    DuplicateDependency,
45}
46
47/// Risk level for a recommendation
48#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
49pub enum RiskLevel {
50    /// No risk, purely optimization
51    None,
52    /// Low risk, easily reversible
53    Low,
54    /// Medium risk, may require rebuild
55    Medium,
56    /// High risk, may lose data
57    High,
58}
59
60impl RiskLevel {
61    /// Get color hint for display
62    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    /// Get symbol for display
72    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    /// Format potential savings for display
84    pub fn savings_display(&self) -> String {
85        format_size(self.potential_savings)
86    }
87}
88
89/// Format bytes as human-readable size
90pub 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}