@@ -102,10 +102,10 @@ func setEnvVariablesForCommand(cmd *exec.Cmd, variables map[string]string) {
102102}
103103
104104// Runs given command and sends stdout to given channel. doneCh used to signal that execution ended.
105- func runCommandWithOutput (cmd * exec.Cmd , outputCh chan string , doneCh chan bool ) {
105+ func runCommandWithOutput (cmd * exec.Cmd , outputCh chan [] byte , doneCh chan bool ) {
106106 cmdOutput , err := cmd .StdoutPipe ()
107107 if err != nil {
108- outputCh <- fmt . Sprintf ("Error: %v " , err )
108+ log . Errorln ("Error: " , err )
109109 doneCh <- true
110110 return
111111 }
@@ -114,29 +114,34 @@ func runCommandWithOutput(cmd *exec.Cmd, outputCh chan string, doneCh chan bool)
114114 defer close (dataReadCh )
115115
116116 go func () {
117- defer func () {
118- dataReadCh <- true
119- }()
120-
121117 reader := bufio .NewReader (cmdOutput )
118+ readBuffer := 1024
122119
123120 for {
124- line , err := reader .ReadString ('\n' )
125- if errors .Is (err , io .EOF ) {
121+ data , err := reader .Peek (readBuffer )
122+ switch {
123+ case errors .Is (err , io .EOF ):
126124 log .Infoln ("Read ended with EOF" )
127- break
128- } else if err != nil {
129- log .Infoln ("Read ended with error" , err )
130- outputCh <- fmt .Sprintf ("Error reading from stdout: %v" , err )
125+ outputCh <- data
126+ dataReadCh <- true
131127 return
128+ case err == nil || errors .Is (err , io .ErrShortBuffer ):
129+ log .Infoln ("Read n bytes" , err )
130+ if len (data ) != 0 {
131+ outputCh <- data
132+ _ , err := reader .Discard (len (data ))
133+ if err != nil {
134+ // TODO: what should I do if I want to move the reader
135+ // If I do nothing it can only cause it to be read twice
136+ log .Errorln ("Discard failed" , err )
137+ }
138+ }
132139 }
133- log .Infoln ("Read line: " , line )
134- outputCh <- line
135140 }
136141 }()
137142
138143 if err := cmd .Start (); err != nil {
139- outputCh <- fmt . Sprintf ("Error: %v " , err )
144+ log . Errorln ("Error: " , err )
140145 doneCh <- true
141146 return
142147 }
@@ -147,7 +152,6 @@ func runCommandWithOutput(cmd *exec.Cmd, outputCh chan string, doneCh chan bool)
147152
148153 if err := cmd .Wait (); err != nil {
149154 log .Errorln ("Failed to execute script: " , err )
150- outputCh <- fmt .Sprintf ("Error: %v" , err )
151155 }
152156
153157 doneCh <- true // Signal that the command has finished
@@ -160,8 +164,8 @@ func executeCommandWithProgress(command string, interpreter string, variables ma
160164 cmd := exec .Command (interpreter , command )
161165 setEnvVariablesForCommand (cmd , variables )
162166
163- var bufferedOutput string
164- outputCh := make (chan string )
167+ var bufferedOutput [] byte
168+ outputCh := make (chan [] byte )
165169 defer close (outputCh )
166170 doneCh := make (chan bool )
167171 defer close (doneCh )
@@ -174,19 +178,16 @@ func executeCommandWithProgress(command string, interpreter string, variables ma
174178 for {
175179 select {
176180 case output := <- outputCh :
177- // TODO: this has to be sent to dispatcher back to report to UI
178- // the idea is to send partial output if buffer with given size sent the output to channel
179- log .Info (output )
180-
181- // Append partial to all output
182- bufferedOutput += output
181+ bufferedOutput = append (bufferedOutput , output ... )
183182 case <- ticker .C :
184183 // NOTE: If just message without output is also okay we could send just still running
185184 log .Infoln ("Still running ..." )
185+ log .Infoln (string (bufferedOutput ))
186186 case <- doneCh :
187187 // Execution is done
188188 log .Infoln ("Execution done ..." )
189- return bufferedOutput
189+ log .Infoln (string (bufferedOutput ))
190+ return string (bufferedOutput )
190191 }
191192 }
192193}
0 commit comments