1- import { exec } from 'child_process' ;
1+ import { exec , spawn } from 'child_process' ;
22import { promisify } from 'util' ;
33import { Logger } from '../utils/Logger' ;
44import chalk from 'chalk' ;
@@ -7,26 +7,46 @@ const execAsync = promisify(exec);
77
88export class GitExecutor {
99 /**
10- * Run any Git command safely.
10+ * Execute any Git command with real-time streaming output.
11+ * Best for CLI tools.
1112 */
1213 static async run ( command : string ) : Promise < void > {
13- try {
14- const { stdout, stderr } = await execAsync ( command ) ;
15-
16- if ( stdout . trim ( ) . length > 0 ) {
17- console . log ( chalk . greenBright ( stdout ) ) ; // ✅ print actual output
18- }
19-
20- if ( stderr . trim ( ) . length > 0 ) {
21- console . log ( chalk . yellowBright ( stderr ) ) ; // ⚠️ show warnings/errors
22- }
23- } catch ( err ) {
24- if ( err instanceof Error ) {
25- Logger . error ( `Git command failed: ${ err . message } ` ) ;
26- } else {
27- Logger . error ( 'Git command failed with an unknown error.' ) ;
28- }
29- }
14+ return new Promise ( ( resolve , reject ) => {
15+ const [ cmd , ...args ] = command . split ( ' ' ) ;
16+
17+ Logger . info ( chalk . gray ( `\n$ ${ command } \n` ) ) ; // show actual command
18+
19+ const child = spawn ( cmd , args , {
20+ stdio : [ 'inherit' , 'pipe' , 'pipe' ] , // stdin inherited, output piped
21+ shell : true , // required for commands with flags
22+ } ) ;
23+
24+ // Stream STDOUT live
25+ child . stdout . on ( 'data' , ( data ) => {
26+ process . stdout . write ( chalk . greenBright ( data . toString ( ) ) ) ;
27+ } ) ;
28+
29+ // Stream STDERR live (git status, warnings, errors)
30+ child . stderr . on ( 'data' , ( data ) => {
31+ process . stdout . write ( chalk . yellowBright ( data . toString ( ) ) ) ;
32+ } ) ;
33+
34+ // When command finishes
35+ child . on ( 'close' , ( code ) => {
36+ if ( code === 0 ) {
37+ resolve ( ) ;
38+ } else {
39+ Logger . error ( `❌ Git exited with code ${ code } ` ) ;
40+ reject ( new Error ( `Git failed with exit code ${ code } ` ) ) ;
41+ }
42+ } ) ;
43+
44+ // General fail-safe
45+ child . on ( 'error' , ( err ) => {
46+ Logger . error ( `❌ Failed to execute command: ${ err . message } ` ) ;
47+ reject ( err ) ;
48+ } ) ;
49+ } ) ;
3050 }
3151
3252 /**
0 commit comments