Skip to content

Commit 0e4410d

Browse files
author
Federico Fissore
committed
External processes output is printed on stdout/stderr in a synchronized way.
Thus we are sure that those outputs do not interfere with our own output, otherwise leading to wrongly formatted log messages. Fixes #17 Signed-off-by: Federico Fissore <[email protected]>
1 parent 8620d4b commit 0e4410d

File tree

5 files changed

+88
-24
lines changed

5 files changed

+88
-24
lines changed

Diff for: src/arduino.cc/builder/builder_utils/utils.go

+12-4
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ import (
3333
"arduino.cc/builder/constants"
3434
"arduino.cc/builder/i18n"
3535
"arduino.cc/builder/props"
36+
"arduino.cc/builder/types"
3637
"arduino.cc/builder/utils"
3738
"bytes"
38-
"fmt"
3939
"os"
4040
"os/exec"
4141
"path/filepath"
@@ -319,10 +319,18 @@ func ExecRecipe(properties map[string]string, recipe string, removeUnsetProperti
319319
}
320320

321321
if echoOutput {
322-
command.Stdout = os.Stdout
322+
printToStdOut := func(s string) {
323+
logger.UnformattedFprintln(os.Stdout, s)
324+
}
325+
stdout := &types.BufferedUntilNewLineWriter{PrintFunc: printToStdOut, Buffer: bytes.Buffer{}}
326+
command.Stdout = stdout
323327
}
324328

325-
command.Stderr = os.Stderr
329+
printToStdErr := func(s string) {
330+
logger.UnformattedFprintln(os.Stderr, s)
331+
}
332+
stderr := &types.BufferedUntilNewLineWriter{PrintFunc: printToStdErr, Buffer: bytes.Buffer{}}
333+
command.Stderr = stderr
326334

327335
if echoOutput {
328336
err := command.Run()
@@ -354,7 +362,7 @@ func PrepareCommandForRecipe(properties map[string]string, recipe string, remove
354362
}
355363

356364
if echoCommandLine {
357-
fmt.Println(commandLine)
365+
logger.UnformattedFprintln(os.Stdout, commandLine)
358366
}
359367

360368
return command, nil

Diff for: src/arduino.cc/builder/coan_runner.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import (
3434
"arduino.cc/builder/i18n"
3535
"arduino.cc/builder/props"
3636
"arduino.cc/builder/utils"
37-
"fmt"
37+
"os"
3838
"path/filepath"
3939
"regexp"
4040
)
@@ -74,7 +74,7 @@ func (s *CoanRunner) Run(context map[string]interface{}) error {
7474
command, err := utils.PrepareCommandFilteredArgs(commandLine, filterAllowedArg, logger)
7575

7676
if verbose {
77-
fmt.Println(commandLine)
77+
logger.UnformattedFprintln(os.Stdout, commandLine)
7878
}
7979

8080
sourceBytes, _ := command.Output()

Diff for: src/arduino.cc/builder/ctags_runner.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import (
3434
"arduino.cc/builder/i18n"
3535
"arduino.cc/builder/props"
3636
"arduino.cc/builder/utils"
37-
"fmt"
37+
"os"
3838
)
3939

4040
type CTagsRunner struct{}
@@ -60,7 +60,7 @@ func (s *CTagsRunner) Run(context map[string]interface{}) error {
6060

6161
verbose := context[constants.CTX_VERBOSE].(bool)
6262
if verbose {
63-
fmt.Println(commandLine)
63+
logger.UnformattedFprintln(os.Stdout, commandLine)
6464
}
6565

6666
sourceBytes, err := command.Output()

Diff for: src/arduino.cc/builder/i18n/i18n.go

+41-16
Original file line numberDiff line numberDiff line change
@@ -38,66 +38,91 @@ import (
3838
"regexp"
3939
"strconv"
4040
"strings"
41+
"sync"
4142
)
4243

4344
var PLACEHOLDER = regexp.MustCompile("{(\\d)}")
4445

4546
type Logger interface {
4647
Fprintln(w io.Writer, format string, a ...interface{})
48+
UnformattedFprintln(w io.Writer, s string)
4749
Println(format string, a ...interface{})
4850
Name() string
4951
}
5052

5153
type NoopLogger struct{}
5254

53-
func (s NoopLogger) Fprintln(w io.Writer, format string, a ...interface{}) {}
55+
func (l NoopLogger) Fprintln(w io.Writer, format string, a ...interface{}) {}
5456

55-
func (s NoopLogger) Println(format string, a ...interface{}) {}
57+
func (l NoopLogger) UnformattedFprintln(w io.Writer, format string, a ...interface{}) {}
5658

57-
func (s NoopLogger) Name() string {
59+
func (l NoopLogger) Println(format string, a ...interface{}) {}
60+
61+
func (l NoopLogger) Name() string {
5862
return "noop"
5963
}
6064

6165
type HumanLogger struct{}
6266

63-
func (s HumanLogger) Fprintln(w io.Writer, format string, a ...interface{}) {
64-
fmt.Fprintln(w, Format(format, a...))
67+
func (l HumanLogger) Fprintln(w io.Writer, format string, a ...interface{}) {
68+
fprintln(w, Format(format, a...))
69+
}
70+
71+
func (l HumanLogger) UnformattedFprintln(w io.Writer, s string) {
72+
fprintln(w, s)
6573
}
6674

67-
func (s HumanLogger) Println(format string, a ...interface{}) {
68-
s.Fprintln(os.Stdout, Format(format, a...))
75+
func (l HumanLogger) Println(format string, a ...interface{}) {
76+
fprintln(os.Stdout, Format(format, a...))
6977
}
7078

71-
func (s HumanLogger) Name() string {
79+
func (l HumanLogger) Name() string {
7280
return "human"
7381
}
7482

7583
type MachineLogger struct{}
7684

77-
func (s MachineLogger) printWithoutFormatting(w io.Writer, format string, a []interface{}) {
85+
func (l MachineLogger) printMachineFormattedLogLine(w io.Writer, format string, a []interface{}) {
7886
a = append([]interface{}(nil), a...)
7987
for idx, value := range a {
8088
typeof := reflect.Indirect(reflect.ValueOf(value)).Kind()
8189
if typeof == reflect.String {
8290
a[idx] = url.QueryEscape(value.(string))
8391
}
8492
}
85-
fmt.Fprintf(w, "===%s ||| %s", format, a)
86-
fmt.Fprintln(w)
93+
fprintf(w, "===%s ||| %s\n", format, a)
94+
}
95+
96+
func (l MachineLogger) Fprintln(w io.Writer, format string, a ...interface{}) {
97+
l.printMachineFormattedLogLine(w, format, a)
8798
}
8899

89-
func (s MachineLogger) Fprintln(w io.Writer, format string, a ...interface{}) {
90-
s.printWithoutFormatting(w, format, a)
100+
func (l MachineLogger) Println(format string, a ...interface{}) {
101+
l.printMachineFormattedLogLine(os.Stdout, format, a)
91102
}
92103

93-
func (s MachineLogger) Println(format string, a ...interface{}) {
94-
s.printWithoutFormatting(os.Stdout, format, a)
104+
func (l MachineLogger) UnformattedFprintln(w io.Writer, s string) {
105+
fprintln(w, s)
95106
}
96107

97-
func (s MachineLogger) Name() string {
108+
func (l MachineLogger) Name() string {
98109
return "machine"
99110
}
100111

112+
var lock sync.Mutex
113+
114+
func fprintln(w io.Writer, s string) {
115+
lock.Lock()
116+
defer lock.Unlock()
117+
fmt.Fprintln(w, s)
118+
}
119+
120+
func fprintf(w io.Writer, format string, a ...interface{}) {
121+
lock.Lock()
122+
defer lock.Unlock()
123+
fmt.Fprintf(w, format, a)
124+
}
125+
101126
func FromJavaToGoSyntax(s string) string {
102127
submatches := PLACEHOLDER.FindAllStringSubmatch(s, -1)
103128
for _, submatch := range submatches {

Diff for: src/arduino.cc/builder/types/accessories.go

+31
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@
2929

3030
package types
3131

32+
import (
33+
"bytes"
34+
"sync"
35+
)
36+
3237
type UniqueStringQueue []string
3338

3439
func (queue UniqueStringQueue) Len() int { return len(queue) }
@@ -74,3 +79,29 @@ func (queue *UniqueSourceFolderQueue) Pop() interface{} {
7479
func (queue *UniqueSourceFolderQueue) Empty() bool {
7580
return queue.Len() == 0
7681
}
82+
83+
type BufferedUntilNewLineWriter struct {
84+
PrintFunc PrintFunc
85+
Buffer bytes.Buffer
86+
lock sync.Mutex
87+
}
88+
89+
type PrintFunc func(string)
90+
91+
func (w *BufferedUntilNewLineWriter) Write(p []byte) (n int, err error) {
92+
w.lock.Lock()
93+
defer w.lock.Unlock()
94+
95+
writtenToBuffer, err := w.Buffer.Write(p)
96+
if err != nil {
97+
return writtenToBuffer, err
98+
}
99+
100+
bytesUntilNewLine, err := w.Buffer.ReadBytes('\n')
101+
if err != nil && len(bytesUntilNewLine) > 0 {
102+
bytesUntilNewLine = bytesUntilNewLine[:len(bytesUntilNewLine)-1]
103+
w.PrintFunc(string(bytesUntilNewLine))
104+
}
105+
106+
return writtenToBuffer, err
107+
}

0 commit comments

Comments
 (0)