Browse code

engine.Tail() to ignore trailing whitespaces.

In its current form, if an error message has two trailing "\n" instead
of one, an empty line is resulted (see engine/job.go for an example of
such usages).

Skipping all trailing whitespaces will give a better error message.

Signed-off-by: Nghia Tran <nghia@google.com>

Nghia Tran authored on 2015/02/21 12:18:30
Showing 2 changed files
... ...
@@ -5,7 +5,9 @@ import (
5 5
 	"fmt"
6 6
 	"io"
7 7
 	"io/ioutil"
8
+	"strings"
8 9
 	"sync"
10
+	"unicode"
9 11
 )
10 12
 
11 13
 type Output struct {
... ...
@@ -16,25 +18,25 @@ type Output struct {
16 16
 }
17 17
 
18 18
 // Tail returns the n last lines of a buffer
19
-// stripped out of the last \n, if any
19
+// stripped out of trailing white spaces, if any.
20
+//
20 21
 // if n <= 0, returns an empty string
21 22
 func Tail(buffer *bytes.Buffer, n int) string {
22 23
 	if n <= 0 {
23 24
 		return ""
24 25
 	}
25
-	bytes := buffer.Bytes()
26
-	if len(bytes) > 0 && bytes[len(bytes)-1] == '\n' {
27
-		bytes = bytes[:len(bytes)-1]
28
-	}
29
-	for i := buffer.Len() - 2; i >= 0; i-- {
30
-		if bytes[i] == '\n' {
26
+	s := strings.TrimRightFunc(buffer.String(), unicode.IsSpace)
27
+	i := len(s) - 1
28
+	for ; i >= 0 && n > 0; i-- {
29
+		if s[i] == '\n' {
31 30
 			n--
32 31
 			if n == 0 {
33
-				return string(bytes[i+1:])
32
+				break
34 33
 			}
35 34
 		}
36 35
 	}
37
-	return string(bytes)
36
+	// when i == -1, return the whole string which is s[0:]
37
+	return s[i+1:]
38 38
 }
39 39
 
40 40
 // NewOutput returns a new Output object with no destinations attached.
... ...
@@ -111,6 +111,11 @@ func TestTail(t *testing.T) {
111 111
 		"Two\nThree",
112 112
 		"One\nTwo\nThree",
113 113
 	}
114
+	tests["One\nTwo\n\n\n"] = []string{
115
+		"",
116
+		"Two",
117
+		"One\nTwo",
118
+	}
114 119
 	for input, outputs := range tests {
115 120
 		for n, expectedOutput := range outputs {
116 121
 			output := Tail(bytes.NewBufferString(input), n)