commit 5a2334ed6902c2bb1e5a4214267d23f92995760a
Author: Dmitrii Filippov <dmfilippov@google.com>
Date:   Mon Oct 5 16:30:32 2020 +0200

    Fix server.go
    
    server.go processed Typesript output incorrectly when multiple
    lines are concatenated together.
    
    Change-Id: Id2af52df8edf702214aeeab1bae0242d3077c616

diff --git a/polygerrit-ui/server.go b/polygerrit-ui/server.go
index 12b3516..3844b5b 100644
--- a/polygerrit-ui/server.go
+++ b/polygerrit-ui/server.go
@@ -527,38 +527,56 @@ var (
 )
 
 type typescriptLogWriter struct {
-	logger *log.Logger
+	unfinishedLine string
+	logger         *log.Logger
 	// when WaitGroup counter is 0 the compilation is complete
 	compilationDoneWaiter *sync.WaitGroup
 }
 
 func newTypescriptLogWriter(compilationCompleteWaiter *sync.WaitGroup) *typescriptLogWriter {
 	return &typescriptLogWriter{
+		unfinishedLine:        "",
 		logger:                log.New(log.Writer(), "TSC - ", log.Flags()),
 		compilationDoneWaiter: compilationCompleteWaiter,
 	}
 }
 
 func (lw typescriptLogWriter) Write(p []byte) (n int, err error) {
-	text := strings.TrimSpace(string(p))
-	if strings.HasSuffix(text, tsFileChangeDetectedMsg) ||
-		strings.HasSuffix(text, tsStartingCompilation) {
-		lw.compilationDoneWaiter.Add(1)
-	}
-	if tsStartWatchingMsg.MatchString(text) {
-		// A source code can be changed while previous compiler run is in progress.
-		// In this case typescript reruns compilation again almost immediately
-		// after the previous run finishes. To detect this situation, we are
-		// waiting waitForNextChangeInterval before decreasing the counter.
-		// If another compiler run is started in this interval, we will wait
-		// again until it finishes.
-		go func() {
-			time.Sleep(waitForNextChangeInterval)
-			lw.compilationDoneWaiter.Add(-1)
-		}()
-
-	}
-	lw.logger.Print(text)
+	// The input p can contain several lines and/or the partial line
+	// Code splits the input by EOL marker (\n) and stores the unfinished line
+	// for the next call to Write.
+	partialText := lw.unfinishedLine + string(p)
+	lines := strings.Split(partialText, "\n")
+	fullLines := lines
+	if strings.HasSuffix(partialText, "\n") {
+		lw.unfinishedLine = ""
+	} else {
+		fullLines = lines[:len(lines)-1]
+		lw.unfinishedLine = lines[len(lines)-1]
+	}
+	for _, fullLine := range fullLines {
+		text := strings.TrimSpace(fullLine)
+		if text == "" {
+			continue
+		}
+		if strings.HasSuffix(text, tsFileChangeDetectedMsg) ||
+			strings.HasSuffix(text, tsStartingCompilation) {
+			lw.compilationDoneWaiter.Add(1)
+		}
+		if tsStartWatchingMsg.MatchString(text) {
+			// A source code can be changed while previous compiler run is in progress.
+			// In this case typescript reruns compilation again almost immediately
+			// after the previous run finishes. To detect this situation, we are
+			// waiting waitForNextChangeInterval before decreasing the counter.
+			// If another compiler run is started in this interval, we will wait
+			// again until it finishes.
+			go func() {
+				time.Sleep(waitForNextChangeInterval)
+				lw.compilationDoneWaiter.Add(-1)
+			}()
+		}
+		lw.logger.Print(text)
+	}
 	return len(p), nil
 }