1use anyhow::Result;
2use chrono::{DateTime, Datelike, Duration, NaiveDate, Utc};
3use git2::Repository;
4use serde_json::{Value, json};
5use std::collections::HashMap;
6
7pub fn get_repo_path() -> Result<String> {
8 let repo = Repository::discover(".")?;
9 let path = repo
10 .path()
11 .parent()
12 .ok_or_else(|| anyhow::anyhow!("Could not get repo path"))?;
13 Ok(path.to_string_lossy().to_string())
14}
15
16pub fn analyze_local_repo() -> Result<Value> {
17 let repo = Repository::discover(".")?;
18
19 let config = repo.config()?;
21 let user_name = config
22 .get_string("user.name")
23 .unwrap_or_else(|_| "Unknown".to_string());
24 let user_email = config
25 .get_string("user.email")
26 .unwrap_or_else(|_| "".to_string());
27
28 let mut revwalk = repo.revwalk()?;
30 revwalk.push_head()?;
31
32 let now = Utc::now();
33 let one_year_ago = now - Duration::weeks(52);
34
35 let mut commits_by_date: HashMap<NaiveDate, u32> = HashMap::new();
36 let mut total_commits = 0;
37
38 for oid in revwalk {
39 let oid = oid?;
40 let commit = repo.find_commit(oid)?;
41
42 let commit_time = commit.time();
43 let timestamp = commit_time.seconds();
44 let datetime =
45 DateTime::from_timestamp(timestamp, 0).ok_or_else(|| anyhow::anyhow!("Invalid timestamp"))?;
46
47 if datetime < one_year_ago {
49 continue;
50 }
51
52 let date = datetime.date_naive();
53 *commits_by_date.entry(date).or_insert(0) += 1;
54 total_commits += 1;
55 }
56
57 let mut weeks = Vec::new();
59 let mut current_date = one_year_ago.date_naive();
60
61 while current_date.weekday().num_days_from_sunday() != 0 {
63 current_date = current_date
64 .pred_opt()
65 .ok_or_else(|| anyhow::anyhow!("Date calculation error"))?;
66 }
67
68 for _ in 0..52 {
69 let mut week_days = Vec::new();
70
71 for _ in 0..7 {
72 let count = commits_by_date.get(¤t_date).copied().unwrap_or(0);
73 week_days.push(json!({
74 "contributionCount": count,
75 "date": current_date.format("%Y-%m-%d").to_string(),
76 }));
77
78 current_date = current_date
79 .succ_opt()
80 .ok_or_else(|| anyhow::anyhow!("Date calculation error"))?;
81 }
82
83 weeks.push(json!({
84 "contributionDays": week_days
85 }));
86 }
87
88 Ok(json!({
89 "name": user_name,
90 "email": user_email,
91 "bio": format!("Local repository: {}", get_repo_path()?),
92 "company": "",
93 "website": "",
94 "total_repos": 1,
95 "total_stars": 0,
96 "total_forks": 0,
97 "languages": {},
98 "contribution_graph": weeks,
99 "current_streak": 0,
100 "longest_streak": 0,
101 "total_contributions": total_commits,
102 "pull_requests": {
103 "open": 0,
104 "awaiting_review": 0,
105 "mentions": 0
106 },
107 "issues": {
108 "assigned": 0,
109 "created": 0,
110 "mentions": 0
111 },
112 }))
113}