1+ use super :: * ;
2+ use crate :: git:: service:: GitService ;
3+ use tauri:: State ;
4+ use std:: sync:: Arc ;
5+ use tokio:: sync:: Mutex ;
6+ use std:: path:: PathBuf ;
7+ use anyhow:: Result ;
8+
9+ #[ tauri:: command]
10+ pub async fn get_git_config (
11+ git_service : State < ' _ , Arc < Mutex < GitService > > > ,
12+ ) -> Result < GitConfig , String > {
13+ let service = git_service. lock ( ) . await ;
14+ Ok ( service. get_config ( ) . clone ( ) )
15+ }
16+
17+ #[ tauri:: command]
18+ pub async fn update_git_config (
19+ git_service : State < ' _ , Arc < Mutex < GitService > > > ,
20+ config : GitConfig ,
21+ ) -> Result < ( ) , String > {
22+ let mut service = git_service. lock ( ) . await ;
23+ service. update_config ( config)
24+ . map_err ( |e| e. to_string ( ) )
25+ }
26+
27+ #[ tauri:: command]
28+ pub async fn detect_git_repository (
29+ git_service : State < ' _ , Arc < Mutex < GitService > > > ,
30+ ) -> Result < GitStatus , String > {
31+ let service = git_service. lock ( ) . await ;
32+ service. detect_repository ( ) . await
33+ . map_err ( |e| e. to_string ( ) )
34+ }
35+
36+ #[ tauri:: command]
37+ pub async fn initialize_git_repository (
38+ git_service : State < ' _ , Arc < Mutex < GitService > > > ,
39+ options : GitInitOptions ,
40+ ) -> Result < ( ) , String > {
41+ let service = git_service. lock ( ) . await ;
42+ service. initialize_repository ( options) . await
43+ . map_err ( |e| e. to_string ( ) )
44+ }
45+
46+ #[ tauri:: command]
47+ pub async fn get_git_status (
48+ git_service : State < ' _ , Arc < Mutex < GitService > > > ,
49+ ) -> Result < GitStatus , String > {
50+ let service = git_service. lock ( ) . await ;
51+ service. get_status ( ) . await
52+ . map_err ( |e| e. to_string ( ) )
53+ }
54+
55+ #[ tauri:: command]
56+ pub async fn commit_git_changes (
57+ git_service : State < ' _ , Arc < Mutex < GitService > > > ,
58+ options : CommitOptions ,
59+ ) -> Result < String , String > {
60+ let service = git_service. lock ( ) . await ;
61+ service. commit_changes ( options) . await
62+ . map_err ( |e| e. to_string ( ) )
63+ }
64+
65+ #[ tauri:: command]
66+ pub async fn get_git_history (
67+ git_service : State < ' _ , Arc < Mutex < GitService > > > ,
68+ page : u32 ,
69+ per_page : u32 ,
70+ ) -> Result < GitHistory , String > {
71+ let service = git_service. lock ( ) . await ;
72+ service. get_history ( page, per_page) . await
73+ . map_err ( |e| e. to_string ( ) )
74+ }
75+
76+ #[ tauri:: command]
77+ pub async fn get_git_diff (
78+ git_service : State < ' _ , Arc < Mutex < GitService > > > ,
79+ commit_hash : Option < String > ,
80+ file_path : Option < String > ,
81+ ) -> Result < Vec < GitDiff > , String > {
82+ let service = git_service. lock ( ) . await ;
83+ service. get_diff (
84+ commit_hash. as_deref ( ) ,
85+ file_path. as_deref ( )
86+ ) . await
87+ . map_err ( |e| e. to_string ( ) )
88+ }
89+
90+ #[ tauri:: command]
91+ pub async fn auto_commit_session (
92+ git_service : State < ' _ , Arc < Mutex < GitService > > > ,
93+ session_name : String ,
94+ ) -> Result < Option < String > , String > {
95+ let service = git_service. lock ( ) . await ;
96+ service. auto_commit_session ( & session_name) . await
97+ . map_err ( |e| e. to_string ( ) )
98+ }
99+
100+ #[ tauri:: command]
101+ pub async fn auto_commit_content_generation (
102+ git_service : State < ' _ , Arc < Mutex < GitService > > > ,
103+ content_types : Vec < String > ,
104+ ) -> Result < Option < String > , String > {
105+ let service = git_service. lock ( ) . await ;
106+ service. auto_commit_content_generation ( & content_types) . await
107+ . map_err ( |e| e. to_string ( ) )
108+ }
109+
110+ #[ tauri:: command]
111+ pub async fn check_git_installation ( ) -> Result < GitInstallationInfo , String > {
112+ // Check if git is installed and get version
113+ let output = std:: process:: Command :: new ( "git" )
114+ . args ( & [ "--version" ] )
115+ . output ( ) ;
116+
117+ match output {
118+ Ok ( output) if output. status . success ( ) => {
119+ let version_str = String :: from_utf8_lossy ( & output. stdout ) ;
120+ let version = version_str. trim ( ) . strip_prefix ( "git version " )
121+ . unwrap_or ( "unknown" )
122+ . to_string ( ) ;
123+
124+ Ok ( GitInstallationInfo {
125+ is_installed : true ,
126+ version : Some ( version) ,
127+ path : which_git ( ) . await . ok ( ) ,
128+ error : None ,
129+ } )
130+ }
131+ Ok ( output) => {
132+ let error = String :: from_utf8_lossy ( & output. stderr ) ;
133+ Ok ( GitInstallationInfo {
134+ is_installed : false ,
135+ version : None ,
136+ path : None ,
137+ error : Some ( error. to_string ( ) ) ,
138+ } )
139+ }
140+ Err ( e) => {
141+ Ok ( GitInstallationInfo {
142+ is_installed : false ,
143+ version : None ,
144+ path : None ,
145+ error : Some ( e. to_string ( ) ) ,
146+ } )
147+ }
148+ }
149+ }
150+
151+ #[ tauri:: command]
152+ pub async fn get_git_user_config ( ) -> Result < GitUserConfig , String > {
153+ let name_result = std:: process:: Command :: new ( "git" )
154+ . args ( & [ "config" , "--global" , "user.name" ] )
155+ . output ( ) ;
156+
157+ let email_result = std:: process:: Command :: new ( "git" )
158+ . args ( & [ "config" , "--global" , "user.email" ] )
159+ . output ( ) ;
160+
161+ let name = if let Ok ( output) = name_result {
162+ if output. status . success ( ) {
163+ Some ( String :: from_utf8_lossy ( & output. stdout ) . trim ( ) . to_string ( ) )
164+ } else {
165+ None
166+ }
167+ } else {
168+ None
169+ } ;
170+
171+ let email = if let Ok ( output) = email_result {
172+ if output. status . success ( ) {
173+ Some ( String :: from_utf8_lossy ( & output. stdout ) . trim ( ) . to_string ( ) )
174+ } else {
175+ None
176+ }
177+ } else {
178+ None
179+ } ;
180+
181+ Ok ( GitUserConfig { name, email } )
182+ }
183+
184+ #[ tauri:: command]
185+ pub async fn set_git_user_config (
186+ name : Option < String > ,
187+ email : Option < String > ,
188+ ) -> Result < ( ) , String > {
189+ if let Some ( name) = name {
190+ let output = std:: process:: Command :: new ( "git" )
191+ . args ( & [ "config" , "--global" , "user.name" , & name] )
192+ . output ( )
193+ . map_err ( |e| format ! ( "Failed to set git user name: {}" , e) ) ?;
194+
195+ if !output. status . success ( ) {
196+ return Err ( format ! ( "Failed to set git user name: {}" ,
197+ String :: from_utf8_lossy( & output. stderr) ) ) ;
198+ }
199+ }
200+
201+ if let Some ( email) = email {
202+ let output = std:: process:: Command :: new ( "git" )
203+ . args ( & [ "config" , "--global" , "user.email" , & email] )
204+ . output ( )
205+ . map_err ( |e| format ! ( "Failed to set git user email: {}" , e) ) ?;
206+
207+ if !output. status . success ( ) {
208+ return Err ( format ! ( "Failed to set git user email: {}" ,
209+ String :: from_utf8_lossy( & output. stderr) ) ) ;
210+ }
211+ }
212+
213+ Ok ( ( ) )
214+ }
215+
216+ #[ tauri:: command]
217+ pub async fn validate_repository_path (
218+ path : String ,
219+ ) -> Result < RepositoryValidation , String > {
220+ let path_buf = PathBuf :: from ( & path) ;
221+
222+ if !path_buf. exists ( ) {
223+ return Ok ( RepositoryValidation {
224+ is_valid : false ,
225+ is_git_repository : false ,
226+ can_initialize : path_buf. parent ( ) . map ( |p| p. exists ( ) ) . unwrap_or ( false ) ,
227+ error_message : Some ( "Path does not exist" . to_string ( ) ) ,
228+ } ) ;
229+ }
230+
231+ if !path_buf. is_dir ( ) {
232+ return Ok ( RepositoryValidation {
233+ is_valid : false ,
234+ is_git_repository : false ,
235+ can_initialize : false ,
236+ error_message : Some ( "Path is not a directory" . to_string ( ) ) ,
237+ } ) ;
238+ }
239+
240+ // Check if it's already a git repository
241+ let git_dir = path_buf. join ( ".git" ) ;
242+ let is_git_repo = git_dir. exists ( ) ;
243+
244+ Ok ( RepositoryValidation {
245+ is_valid : true ,
246+ is_git_repository : is_git_repo,
247+ can_initialize : !is_git_repo,
248+ error_message : None ,
249+ } )
250+ }
251+
252+ // Helper function to find git executable
253+ async fn which_git ( ) -> Result < PathBuf > {
254+ let output = std:: process:: Command :: new ( "which" )
255+ . args ( & [ "git" ] )
256+ . output ( ) ?;
257+
258+ if output. status . success ( ) {
259+ let path_str = String :: from_utf8_lossy ( & output. stdout ) ;
260+ Ok ( PathBuf :: from ( path_str. trim ( ) ) )
261+ } else {
262+ Err ( anyhow:: anyhow!( "Git executable not found in PATH" ) )
263+ }
264+ }
265+
266+ #[ derive( Debug , Clone , serde:: Serialize , serde:: Deserialize ) ]
267+ pub struct GitInstallationInfo {
268+ pub is_installed : bool ,
269+ pub version : Option < String > ,
270+ pub path : Option < PathBuf > ,
271+ pub error : Option < String > ,
272+ }
273+
274+ #[ derive( Debug , Clone , serde:: Serialize , serde:: Deserialize ) ]
275+ pub struct GitUserConfig {
276+ pub name : Option < String > ,
277+ pub email : Option < String > ,
278+ }
279+
280+ #[ derive( Debug , Clone , serde:: Serialize , serde:: Deserialize ) ]
281+ pub struct RepositoryValidation {
282+ pub is_valid : bool ,
283+ pub is_git_repository : bool ,
284+ pub can_initialize : bool ,
285+ pub error_message : Option < String > ,
286+ }
0 commit comments