@@ -42,122 +42,127 @@ public struct GitShell {
4242 var stderr = " "
4343
4444 let process = Process ( )
45- process. launchPath = " /usr/bin/env "
45+ process. executableURL = URL ( fileURLWithPath : " /usr/bin/env " )
4646 process. arguments = [ " git " ] + args
47- process. currentDirectoryPath = path. relativePath
47+ process. currentDirectoryURL = path
4848
4949 let stdoutPipe = Pipe ( )
5050 let stderrPipe = Pipe ( )
5151 process. standardOutput = stdoutPipe
5252 process. standardError = stderrPipe
5353
54- let environment = ProcessInfo . processInfo. environment
55-
56- // Set TERM to 'dumb' in the environment
57- var gitEnvironment = environment
54+ var gitEnvironment = ProcessInfo . processInfo. environment
5855 gitEnvironment [ " TERM " ] = " dumb "
5956
6057 if let environment = options? . env {
61- process . environment = environment
58+ gitEnvironment . merge ( environment) { ( _ , new ) in new }
6259 }
6360
6461 process. environment = gitEnvironment
6562
66- process. launch ( )
63+ do {
64+ try process. run ( )
65+ } catch {
66+ throw ProcessError . launchFailed ( error. localizedDescription)
67+ }
68+
69+ let stdoutHandle = stdoutPipe. fileHandleForReading
70+ let stderrHandle = stderrPipe. fileHandleForReading
71+
72+ stdoutHandle. readabilityHandler = { handle in
73+ let data = handle. availableData
74+ if let output = String ( data: data, encoding: . utf8) {
75+ stdout += output
76+ }
77+ }
78+
79+ stderrHandle. readabilityHandler = { handle in
80+ let data = handle. availableData
81+ if let output = String ( data: data, encoding: . utf8) {
82+ stderr += output
83+ }
84+ }
6785
6886 let commandLineURL = " /usr/bin/env git " + args. joined ( separator: " " )
6987 print ( " Command Line URL: \( commandLineURL) " )
7088
71- let stdoutData = stdoutPipe. fileHandleForReading. readDataToEndOfFile ( )
72- if let output = String ( data: stdoutData, encoding: . utf8) {
73- stdout = output
89+ let timeout : TimeInterval = 30 // Adjust this value as needed
90+ let timeoutDate = Date ( timeIntervalSinceNow: timeout)
91+
92+ while process. isRunning && Date ( ) < timeoutDate {
93+ Thread . sleep ( forTimeInterval: 0.1 )
7494 }
7595
76- let stderrData = stderrPipe . fileHandleForReading . readDataToEndOfFile ( )
77- if let errorOutput = String ( data : stderrData , encoding : . utf8 ) {
78- stderr = errorOutput
96+ if process . isRunning {
97+ process . terminate ( )
98+ throw ProcessError . timeout
7999 }
80100
81- process. waitUntilExit ( )
101+ stdoutHandle. readabilityHandler = nil
102+ stderrHandle. readabilityHandler = nil
82103
83- let combinedOuput = stdout + stderr
104+ let exitCode = Int ( process . terminationStatus )
84105
85- print ( " Function: \( name ) , Output: \( stdout) " )
106+ let combinedOutput = stdout + stderr
86107
87108 let result = IGitResult ( stdout: stdout,
88109 stderr: stderr,
89- exitCode: Int ( process . terminationStatus ) ,
110+ exitCode: exitCode ,
90111 gitError: nil ,
91112 gitErrorDescription: nil ,
92- combinedOutput: stdout + stderr ,
113+ combinedOutput: combinedOutput ,
93114 path: path. relativePath. escapedWhiteSpaces ( ) )
94115
95- let exitCode = result. exitCode
96- var gitError : GitError ?
97- let acceptableExitCode = options? . successExitCodes != nil
98- ? options? . successExitCodes? . contains ( exitCode)
99- : false
100-
101- if !acceptableExitCode! {
102- gitError = parseError ( stderr: result. stderr)
103- if gitError == nil {
104- gitError = parseError ( stderr: result. stdout)
105- }
106- }
116+ let acceptableExitCode = options? . successExitCodes? . contains ( exitCode) ?? ( exitCode == 0 )
107117
108- let gitErrorDescription = gitError != nil ? getDescriptionError ( gitError!) : nil
118+ if !acceptableExitCode {
119+ let gitError = parseError ( stderr: result. stderr) ?? parseError ( stderr: result. stdout)
120+ let gitErrorDescription = gitError. map { getDescriptionError ( $0) }
109121
110- var gitResult = IGitResult ( stdout: stdout,
111- stderr: stderr,
112- exitCode: exitCode,
113- gitError: gitError,
114- gitErrorDescription: gitErrorDescription,
115- combinedOutput: combinedOuput ,
116- path: path. relativePath. escapedWhiteSpaces ( ) )
122+ var gitResult = IGitResult ( stdout: stdout,
123+ stderr: stderr,
124+ exitCode: exitCode,
125+ gitError: gitError,
126+ gitErrorDescription: gitErrorDescription ?? " Unknown error " ,
127+ combinedOutput: combinedOutput ,
128+ path: path. relativePath. escapedWhiteSpaces ( ) )
117129
118- var acceptableError = true
130+ let acceptableError = gitError . map { options ? . expectedErrors ? . contains ( $0 ) ?? false } ?? false
119131
120- if gitError != nil && options ? . expectedErrors != nil {
121- acceptableError = ( ( options ? . expectedErrors ? . contains ( gitError! ) ) != nil )
122- }
132+ if acceptableError {
133+ return gitResult
134+ }
123135
124- if ( gitError != nil && acceptableError) || acceptableError {
125- return gitResult
126- }
136+ var errorMessage = [ String] ( )
137+ errorMessage. append ( " `git \( args. joined ( separator: " " ) ) ` exited with an unexpected code: \( exitCode) " )
127138
128- var errorMessage = [ String] ( )
139+ if !result. stdout. isEmpty {
140+ errorMessage. append ( " stdout: " )
141+ errorMessage. append ( result. stdout)
142+ }
129143
130- errorMessage. append ( " `git \( args. joined ( separator: " " ) ) ` exited with an unexpected code: \( exitCode) " )
144+ if !result. stderr. isEmpty {
145+ errorMessage. append ( " stderr: " )
146+ errorMessage. append ( result. stderr)
147+ }
131148
132- if !result. stdout. isEmpty {
133- errorMessage. append ( " stdout: " )
134- errorMessage. append ( result. stdout)
135- }
149+ if let gitError = gitError {
150+ errorMessage. append ( " (The error was parsed as \( gitError) : \( gitErrorDescription ?? " " ) ) " )
151+ }
136152
137- if !result. stderr. isEmpty {
138- errorMessage. append ( " stderr: " )
139- errorMessage. append ( result. stderr)
140- }
153+ if gitError == . PushWithFileSizeExceedingLimit {
154+ if let files = getFileFromExceedsError ( error: errorMessage. joined ( separator: " \n " ) ) {
155+ gitResult. gitErrorDescription? += " \n \n File causing error: \n \n " + files. joined ( separator: " \n " )
156+ }
157+ }
141158
142- if let gitError = gitError {
143- errorMessage. append ( " (The error was parsed as \( gitError) : \( gitErrorDescription ?? " " ) ) " )
159+ throw ProcessError . unexpectedExitCode ( exitCode)
144160 }
145161
146- let errorString = errorMessage. joined ( separator: " \n " )
147-
148- print ( errorMessage. joined ( separator: " \n " ) )
149-
150- if gitError == GitError . PushWithFileSizeExceedingLimit {
151- let result = getFileFromExceedsError ( error: errorMessage. joined ( ) )
152- let files = result. joined ( separator: " \n " )
153-
154- if !files. isEmpty {
155- gitResult. gitErrorDescription! += " \n \n File causing error: \n \n " + files
156- }
157- }
162+ try ? stdoutHandle. close ( )
163+ try ? stderrHandle. close ( )
158164
159- throw GitErrorParser ( result: gitResult,
160- args: args)
165+ return result
161166 }
162167
163168 /**
@@ -291,7 +296,7 @@ public struct GitShell {
291296 }
292297 }
293298
294- func getFileFromExceedsError( error: String ) -> [ String ] {
299+ func getFileFromExceedsError( error: String ) -> [ String ] ? {
295300 do {
296301 let beginRegex = try NSRegularExpression (
297302 pattern: " (^remote: \\ serror: \\ sFile \\ s) " ,
@@ -314,7 +319,7 @@ public struct GitShell {
314319 )
315320
316321 if beginMatches. count != endMatches. count {
317- return [ ]
322+ return nil // Changed from [] to nil
318323 }
319324
320325 var files : [ String ] = [ ]
@@ -328,9 +333,9 @@ public struct GitShell {
328333 files. append ( file)
329334 }
330335
331- return files
336+ return files. isEmpty ? nil : files // Return nil if no files found
332337 } catch {
333- return [ ]
338+ return nil // Changed from [] to nil
334339 }
335340 }
336341}
0 commit comments