git-slop 0.10.1

A deterministic repository token-defragmenter for humans and AI agents.
Documentation
use std::fs;
use std::path::Path;

use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::config;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnalysisEstimate {
    pub tracked_path_count: usize,
    pub inventory_bytes: u128,
    pub estimated_peak_memory_bytes: u128,
    pub memory_budget_bytes: u128,
    pub estimated_cache_bytes: u128,
    pub estimated_report_bytes: u128,
    pub estimated_inode_count: u128,
    pub estimated_seconds: u128,
}

pub fn build(repo_root: &Path, paths: &[String], config_value: &Value) -> AnalysisEstimate {
    let inventory_bytes = paths
        .iter()
        .filter_map(|path| fs::metadata(repo_root.join(path)).ok())
        .map(|metadata| metadata.len() as u128)
        .sum::<u128>();
    let path_count = paths.len() as u128;
    let pair_limit =
        config::pointer_u64(config_value, "/organization/max_pairs_per_file", 20) as u128;
    let graph_bytes = path_count.saturating_mul(pair_limit).saturating_mul(256);
    let history_bytes = path_count.saturating_mul(1_024);
    let tokenizer_bytes = inventory_bytes.saturating_mul(2);
    let report_bytes = inventory_bytes
        .saturating_div(2)
        .saturating_add(path_count.saturating_mul(4_096));
    let estimated_peak_memory_bytes = inventory_bytes
        .saturating_add(tokenizer_bytes)
        .saturating_add(graph_bytes)
        .saturating_add(history_bytes)
        .saturating_add(report_bytes);
    AnalysisEstimate {
        tracked_path_count: paths.len(),
        inventory_bytes,
        estimated_peak_memory_bytes,
        memory_budget_bytes: config::pointer_u64(config_value, "/resources/memory_budget_mb", 1024)
            as u128
            * 1024
            * 1024,
        estimated_cache_bytes: inventory_bytes
            .saturating_div(3)
            .saturating_add(path_count * 512),
        estimated_report_bytes: report_bytes,
        estimated_inode_count: path_count.saturating_add(16),
        estimated_seconds: inventory_bytes
            .div_ceil(8 * 1024 * 1024)
            .saturating_add(path_count.div_ceil(2_000))
            .max(1),
    }
}