@@ -8,12 +8,14 @@ use std::path::PathBuf;
88mod advanced_handlers;
99mod benchmark;
1010mod comparison_handlers;
11+ mod git_integration;
1112mod production_handlers;
1213mod report_handlers;
1314mod scan_handlers;
1415mod utils;
1516
1617use advanced_handlers:: * ;
18+ use git_integration:: GitIntegration ;
1719use production_handlers:: * ;
1820
1921#[ derive( Parser ) ]
@@ -243,6 +245,11 @@ enum Commands {
243245 #[ arg( long, default_value = "500" ) ]
244246 delay : u64 ,
245247 } ,
248+ /// Git integration and hook management
249+ Git {
250+ #[ command( subcommand) ]
251+ action : GitAction ,
252+ } ,
246253}
247254
248255#[ derive( Subcommand ) ]
@@ -349,6 +356,28 @@ enum StackPreset {
349356 } ,
350357}
351358
359+ #[ derive( Subcommand ) ]
360+ enum GitAction {
361+ /// Install pre-commit hook
362+ InstallHook {
363+ /// Path to git repository (default: current directory)
364+ #[ arg( default_value = "." ) ]
365+ path : PathBuf ,
366+ } ,
367+ /// Uninstall pre-commit hook
368+ UninstallHook {
369+ /// Path to git repository (default: current directory)
370+ #[ arg( default_value = "." ) ]
371+ path : PathBuf ,
372+ } ,
373+ /// List staged files that would be scanned
374+ Staged {
375+ /// Path to git repository (default: current directory)
376+ #[ arg( default_value = "." ) ]
377+ path : PathBuf ,
378+ } ,
379+ }
380+
352381fn main ( ) -> Result < ( ) > {
353382 let cli = Cli :: parse ( ) ;
354383
@@ -435,13 +464,14 @@ fn main() -> Result<()> {
435464 format,
436465 production,
437466 } => handle_lang_scan ( languages, path, format, production) ,
438- Commands :: Stack { preset } => handle_stack_preset ( preset) ,
467+ Commands :: Stack { preset } => handle_stack_preset_main ( preset) ,
439468 Commands :: Watch {
440469 path,
441470 include,
442471 exclude,
443472 delay,
444473 } => handle_watch ( path, include, exclude, delay) ,
474+ Commands :: Git { action } => handle_git ( action) ,
445475 }
446476}
447477
@@ -484,6 +514,116 @@ fn handle_benchmark(path: Option<PathBuf>, quick: bool) -> Result<()> {
484514 }
485515}
486516
517+ fn handle_stack_preset_main ( preset : StackPreset ) -> Result < ( ) > {
518+ match preset {
519+ StackPreset :: Web { path, production } => {
520+ let languages = vec ! [
521+ "js" . to_string( ) ,
522+ "ts" . to_string( ) ,
523+ "jsx" . to_string( ) ,
524+ "tsx" . to_string( ) ,
525+ "vue" . to_string( ) ,
526+ "svelte" . to_string( ) ,
527+ ] ;
528+ handle_lang_scan ( languages, path, "text" . to_string ( ) , production)
529+ }
530+ StackPreset :: Backend { path, production } => {
531+ let languages = vec ! [
532+ "py" . to_string( ) ,
533+ "java" . to_string( ) ,
534+ "go" . to_string( ) ,
535+ "cs" . to_string( ) ,
536+ "php" . to_string( ) ,
537+ "rb" . to_string( ) ,
538+ ] ;
539+ handle_lang_scan ( languages, path, "text" . to_string ( ) , production)
540+ }
541+ StackPreset :: Fullstack { path, production } => {
542+ let languages = vec ! [
543+ "js" . to_string( ) ,
544+ "ts" . to_string( ) ,
545+ "py" . to_string( ) ,
546+ "java" . to_string( ) ,
547+ "go" . to_string( ) ,
548+ "rs" . to_string( ) ,
549+ ] ;
550+ handle_lang_scan ( languages, path, "text" . to_string ( ) , production)
551+ }
552+ StackPreset :: Mobile { path, production } => {
553+ let languages = vec ! [
554+ "js" . to_string( ) ,
555+ "ts" . to_string( ) ,
556+ "swift" . to_string( ) ,
557+ "kt" . to_string( ) ,
558+ "dart" . to_string( ) ,
559+ ] ;
560+ handle_lang_scan ( languages, path, "text" . to_string ( ) , production)
561+ }
562+ StackPreset :: Systems { path, production } => {
563+ let languages = vec ! [
564+ "rs" . to_string( ) ,
565+ "cpp" . to_string( ) ,
566+ "c" . to_string( ) ,
567+ "go" . to_string( ) ,
568+ ] ;
569+ handle_lang_scan ( languages, path, "text" . to_string ( ) , production)
570+ }
571+ }
572+ }
573+
574+ fn handle_git ( action : GitAction ) -> Result < ( ) > {
575+ match action {
576+ GitAction :: InstallHook { path } => {
577+ println ! ( "🔧 Installing Code-Guardian pre-commit hook..." ) ;
578+
579+ if !GitIntegration :: is_git_repo ( & path) {
580+ eprintln ! ( "❌ Error: {} is not a git repository" , path. display( ) ) ;
581+ std:: process:: exit ( 1 ) ;
582+ }
583+
584+ let repo_root = GitIntegration :: get_repo_root ( & path) ?;
585+ GitIntegration :: install_pre_commit_hook ( & repo_root) ?;
586+
587+ println ! ( "💡 Usage: The hook will automatically run on 'git commit'" ) ;
588+ println ! ( "💡 Manual run: code-guardian pre-commit --staged-only --fast" ) ;
589+ Ok ( ( ) )
590+ }
591+ GitAction :: UninstallHook { path } => {
592+ println ! ( "🗑️ Uninstalling Code-Guardian pre-commit hook..." ) ;
593+
594+ if !GitIntegration :: is_git_repo ( & path) {
595+ eprintln ! ( "❌ Error: {} is not a git repository" , path. display( ) ) ;
596+ std:: process:: exit ( 1 ) ;
597+ }
598+
599+ let repo_root = GitIntegration :: get_repo_root ( & path) ?;
600+ GitIntegration :: uninstall_pre_commit_hook ( & repo_root) ?;
601+ Ok ( ( ) )
602+ }
603+ GitAction :: Staged { path } => {
604+ println ! ( "📋 Listing staged files..." ) ;
605+
606+ if !GitIntegration :: is_git_repo ( & path) {
607+ eprintln ! ( "❌ Error: {} is not a git repository" , path. display( ) ) ;
608+ std:: process:: exit ( 1 ) ;
609+ }
610+
611+ let repo_root = GitIntegration :: get_repo_root ( & path) ?;
612+ let staged_files = GitIntegration :: get_staged_files ( & repo_root) ?;
613+
614+ if staged_files. is_empty ( ) {
615+ println ! ( "ℹ️ No staged files found." ) ;
616+ } else {
617+ println ! ( "🔍 Found {} staged file(s):" , staged_files. len( ) ) ;
618+ for ( i, file) in staged_files. iter ( ) . enumerate ( ) {
619+ println ! ( " {}. {}" , i + 1 , file. display( ) ) ;
620+ }
621+ }
622+ Ok ( ( ) )
623+ }
624+ }
625+ }
626+
487627#[ cfg( test) ]
488628mod tests {
489629 use super :: * ;
0 commit comments