Skip to content

Commit 38e0c71

Browse files
committed
feat(main): implement multi-profile CLI with config-driven analysis
Replace single --repo flag with --config (default: config.toml). For each profile and each repo in config: - Clone or fetch repo into ~/.cache/git-reports/ - Analyze commits filtered by profile email and --period - Serialize results as JSON array to --output or stdout
1 parent cc87b0b commit 38e0c71

1 file changed

Lines changed: 85 additions & 10 deletions

File tree

src/main.rs

Lines changed: 85 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,102 @@
11
use clap::Parser;
2+
use git_reports::analysis::{analyze_repo, clone_or_update};
3+
use git_reports::config::load_config;
4+
use serde_json;
25

36
#[derive(Parser, Debug)]
47
#[command(name = "git-reports")]
58
#[command(about = "Automated Git analytics engine for work summaries", long_about = None)]
69
struct Args {
7-
/// Path to the Git repository
8-
#[arg(short, long, default_value = ".")]
9-
repo: String,
10+
/// Ruta al archivo de configuración (config.toml)
11+
#[arg(short, long, default_value = "config.toml")]
12+
config: String,
1013

11-
/// Output file path (JSON)
14+
/// Archivo de salida JSON (por defecto imprime a stdout)
1215
#[arg(short, long)]
1316
output: Option<String>,
1417

15-
/// Time period: week, month, all
18+
/// Periodo de análisis: week, month, all
1619
#[arg(short, long, default_value = "week")]
1720
period: String,
1821
}
1922

2023
fn main() {
2124
let args = Args::parse();
22-
println!("Git Reports - Analyzing repository: {}", args.repo);
23-
println!("Period: {}", args.period);
24-
25-
// TODO: Implement Git analysis
26-
println!("Analysis complete!");
25+
26+
// Cargar configuración
27+
let config = match load_config(&args.config) {
28+
Ok(c) => c,
29+
Err(e) => {
30+
eprintln!("Error: {}", e);
31+
std::process::exit(1);
32+
}
33+
};
34+
35+
eprintln!(
36+
"Git Reports — {} perfil(es) encontrado(s), periodo: {}",
37+
config.profile.len(),
38+
args.period
39+
);
40+
41+
let mut all_reports: Vec<serde_json::Value> = Vec::new();
42+
43+
for profile in &config.profile {
44+
eprintln!("\n[perfil: {}] email: {}", profile.name, profile.email);
45+
46+
let mut profile_reports: Vec<serde_json::Value> = Vec::new();
47+
48+
for entry in &profile.repo {
49+
let label = format!("{}/{}/{}", entry.provider, entry.owner, entry.name);
50+
eprintln!(" Procesando {}", label);
51+
52+
// Clonar o actualizar el repo en caché
53+
let repo = match clone_or_update(entry, profile) {
54+
Ok(r) => r,
55+
Err(e) => {
56+
eprintln!(" ✗ Error: {}", e);
57+
continue;
58+
}
59+
};
60+
61+
// Analizar commits filtrados por email y periodo
62+
let report = match analyze_repo(&repo, &args.period, &profile.email, &label) {
63+
Ok(r) => r,
64+
Err(e) => {
65+
eprintln!(" ✗ Error al analizar: {}", e);
66+
continue;
67+
}
68+
};
69+
70+
eprintln!(
71+
" ✓ {} commit(s) encontrado(s) para {}",
72+
report.total_commits, profile.email
73+
);
74+
75+
profile_reports.push(serde_json::to_value(&report).unwrap());
76+
}
77+
78+
all_reports.push(serde_json::json!({
79+
"profile": profile.name,
80+
"email": profile.email,
81+
"repos": profile_reports,
82+
}));
83+
}
84+
85+
// Serializar resultado final
86+
let json = serde_json::to_string_pretty(&all_reports).unwrap_or_else(|e| {
87+
eprintln!("Error al serializar JSON: {}", e);
88+
std::process::exit(1);
89+
});
90+
91+
match &args.output {
92+
Some(path) => {
93+
std::fs::write(path, &json).unwrap_or_else(|e| {
94+
eprintln!("Error al escribir '{}': {}", path, e);
95+
std::process::exit(1);
96+
});
97+
eprintln!("\nReporte guardado en: {}", path);
98+
}
99+
None => println!("{}", json),
100+
}
27101
}
102+

0 commit comments

Comments
 (0)