1use crate::token_optimizer::TokenOptimizer;
2use serde::Serialize;
3use std::fmt;
4
5#[derive(Serialize, Debug, Clone)]
6pub struct CommitContext {
7 pub branch: String,
8 pub recent_commits: Vec<RecentCommit>,
9 pub staged_files: Vec<StagedFile>,
10 pub project_metadata: ProjectMetadata,
11 pub user_name: String,
12 pub user_email: String,
13}
14
15#[derive(Serialize, Debug, Clone)]
16pub struct RecentCommit {
17 pub hash: String,
18 pub message: String,
19 pub author: String,
20 pub timestamp: String,
21}
22
23#[derive(Serialize, Debug, Clone)]
24pub struct StagedFile {
25 pub path: String,
26 pub change_type: ChangeType,
27 pub diff: String,
28 pub analysis: Vec<String>,
29 pub content: Option<String>,
30 pub content_excluded: bool,
31}
32
33#[derive(Serialize, Debug, Clone, PartialEq, Eq)]
34pub enum ChangeType {
35 Added,
36 Modified,
37 Deleted,
38}
39
40impl fmt::Display for ChangeType {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 match self {
43 Self::Added => write!(f, "Added"),
44 Self::Modified => write!(f, "Modified"),
45 Self::Deleted => write!(f, "Deleted"),
46 }
47 }
48}
49
50#[derive(Serialize, Debug, Clone, Default)]
51pub struct ProjectMetadata {
52 pub language: Option<String>,
53 pub framework: Option<String>,
54 pub dependencies: Vec<String>,
55 pub version: Option<String>,
56 pub build_system: Option<String>,
57 pub test_framework: Option<String>,
58 pub plugins: Vec<String>,
59}
60
61impl ProjectMetadata {
62 pub fn merge(&mut self, new: ProjectMetadata) {
63 if let Some(new_lang) = new.language {
64 match &mut self.language {
65 Some(lang) if !lang.contains(&new_lang) => {
66 lang.push_str(", ");
67 lang.push_str(&new_lang);
68 }
69 None => self.language = Some(new_lang),
70 _ => {}
71 }
72 }
73 self.dependencies.extend(new.dependencies.clone());
74 self.framework = self.framework.take().or(new.framework);
75 self.version = self.version.take().or(new.version);
76 self.build_system = self.build_system.take().or(new.build_system);
77 self.test_framework = self.test_framework.take().or(new.test_framework);
78 self.plugins.extend(new.plugins);
79 self.dependencies.sort();
80 self.dependencies.dedup();
81 }
82}
83
84impl CommitContext {
85 pub fn new(
86 branch: String,
87 recent_commits: Vec<RecentCommit>,
88 staged_files: Vec<StagedFile>,
89 project_metadata: ProjectMetadata,
90 user_name: String,
91 user_email: String,
92 ) -> Self {
93 Self {
94 branch,
95 recent_commits,
96 staged_files,
97 project_metadata,
98 user_name,
99 user_email,
100 }
101 }
102 pub fn optimize(&mut self, max_tokens: usize) {
103 let optimizer = TokenOptimizer::new(max_tokens);
104 optimizer.optimize_context(self);
105 }
106}