Remove terminal.Writer
terminal.Writer is now just a wrapper around stdio.Stdout() without any useful functionality. Replace it with stdio.Stdout() as an io.Writer. Test: ui/terminal/status_test.go Change-Id: I5bc5476afdca950b505642f0135a3af9d37fbe24
This commit is contained in:
parent
ce525350f4
commit
097ed2a37c
|
@ -156,10 +156,9 @@ type mpContext struct {
|
|||
}
|
||||
|
||||
func main() {
|
||||
writer := terminal.NewWriter(terminal.StdioImpl{})
|
||||
defer writer.Finish()
|
||||
stdio := terminal.StdioImpl{}
|
||||
|
||||
log := logger.New(writer)
|
||||
log := logger.New(stdio.Stdout())
|
||||
defer log.Cleanup()
|
||||
|
||||
flag.Parse()
|
||||
|
@ -172,7 +171,7 @@ func main() {
|
|||
|
||||
stat := &status.Status{}
|
||||
defer stat.Finish()
|
||||
stat.AddOutput(terminal.NewStatusOutput(writer, "",
|
||||
stat.AddOutput(terminal.NewStatusOutput(stdio.Stdout(), "",
|
||||
build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD")))
|
||||
|
||||
var failures failureCount
|
||||
|
@ -188,7 +187,7 @@ func main() {
|
|||
Context: ctx,
|
||||
Logger: log,
|
||||
Tracer: trace,
|
||||
Writer: writer,
|
||||
Writer: stdio.Stdout(),
|
||||
Status: stat,
|
||||
}}
|
||||
|
||||
|
@ -341,7 +340,7 @@ func main() {
|
|||
} else if failures > 1 {
|
||||
log.Fatalf("%d failures", failures)
|
||||
} else {
|
||||
writer.Print("Success")
|
||||
fmt.Fprintln(stdio.Stdout(), "Success")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -386,7 +385,7 @@ func buildProduct(mpctx *mpContext, product string) {
|
|||
Context: mpctx.Context,
|
||||
Logger: log,
|
||||
Tracer: mpctx.Tracer,
|
||||
Writer: terminal.NewWriter(terminal.NewCustomStdio(nil, f, f)),
|
||||
Writer: f,
|
||||
Thread: mpctx.Tracer.NewThread(product),
|
||||
Status: &status.Status{},
|
||||
}}
|
||||
|
|
|
@ -109,10 +109,7 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
writer := terminal.NewWriter(c.stdio())
|
||||
defer writer.Finish()
|
||||
|
||||
log := logger.New(writer)
|
||||
log := logger.New(c.stdio().Stdout())
|
||||
defer log.Cleanup()
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
@ -125,7 +122,7 @@ func main() {
|
|||
|
||||
stat := &status.Status{}
|
||||
defer stat.Finish()
|
||||
stat.AddOutput(terminal.NewStatusOutput(writer, os.Getenv("NINJA_STATUS"),
|
||||
stat.AddOutput(terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"),
|
||||
build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD")))
|
||||
stat.AddOutput(trace.StatusTracer())
|
||||
|
||||
|
@ -140,7 +137,7 @@ func main() {
|
|||
Logger: log,
|
||||
Metrics: met,
|
||||
Tracer: trace,
|
||||
Writer: writer,
|
||||
Writer: c.stdio().Stdout(),
|
||||
Status: stat,
|
||||
}}
|
||||
|
||||
|
@ -312,13 +309,13 @@ func dumpVarConfig(ctx build.Context, args ...string) build.Config {
|
|||
func make(ctx build.Context, config build.Config, _ []string, logsDir string) {
|
||||
if config.IsVerbose() {
|
||||
writer := ctx.Writer
|
||||
writer.Print("! The argument `showcommands` is no longer supported.")
|
||||
writer.Print("! Instead, the verbose log is always written to a compressed file in the output dir:")
|
||||
writer.Print("!")
|
||||
writer.Print(fmt.Sprintf("! gzip -cd %s/verbose.log.gz | less -R", logsDir))
|
||||
writer.Print("!")
|
||||
writer.Print("! Older versions are saved in verbose.log.#.gz files")
|
||||
writer.Print("")
|
||||
fmt.Fprintln(writer, "! The argument `showcommands` is no longer supported.")
|
||||
fmt.Fprintln(writer, "! Instead, the verbose log is always written to a compressed file in the output dir:")
|
||||
fmt.Fprintln(writer, "!")
|
||||
fmt.Fprintf(writer, "! gzip -cd %s/verbose.log.gz | less -R\n", logsDir)
|
||||
fmt.Fprintln(writer, "!")
|
||||
fmt.Fprintln(writer, "! Older versions are saved in verbose.log.#.gz files")
|
||||
fmt.Fprintln(writer, "")
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
|
||||
|
|
|
@ -22,14 +22,13 @@ import (
|
|||
"testing"
|
||||
|
||||
"android/soong/ui/logger"
|
||||
"android/soong/ui/terminal"
|
||||
)
|
||||
|
||||
func testContext() Context {
|
||||
return Context{&ContextImpl{
|
||||
Context: context.Background(),
|
||||
Logger: logger.New(&bytes.Buffer{}),
|
||||
Writer: terminal.NewWriter(terminal.NewCustomStdio(&bytes.Buffer{}, &bytes.Buffer{}, &bytes.Buffer{})),
|
||||
Writer: &bytes.Buffer{},
|
||||
}}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,12 +16,12 @@ package build
|
|||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"android/soong/ui/logger"
|
||||
"android/soong/ui/metrics"
|
||||
"android/soong/ui/metrics/metrics_proto"
|
||||
"android/soong/ui/status"
|
||||
"android/soong/ui/terminal"
|
||||
"android/soong/ui/tracer"
|
||||
)
|
||||
|
||||
|
@ -35,7 +35,7 @@ type ContextImpl struct {
|
|||
|
||||
Metrics *metrics.Metrics
|
||||
|
||||
Writer terminal.Writer
|
||||
Writer io.Writer
|
||||
Status *status.Status
|
||||
|
||||
Thread tracer.Thread
|
||||
|
|
|
@ -249,7 +249,7 @@ func runMakeProductConfig(ctx Context, config Config) {
|
|||
env := config.Environment()
|
||||
// Print the banner like make does
|
||||
if !env.IsEnvTrue("ANDROID_QUIET_BUILD") {
|
||||
ctx.Writer.Print(Banner(make_vars))
|
||||
fmt.Fprintln(ctx.Writer, Banner(make_vars))
|
||||
}
|
||||
|
||||
// Populate the environment
|
||||
|
|
|
@ -21,7 +21,7 @@ bootstrap_go_package {
|
|||
"format.go",
|
||||
"smart_status.go",
|
||||
"status.go",
|
||||
"writer.go",
|
||||
"stdio.go",
|
||||
"util.go",
|
||||
],
|
||||
testSrcs: [
|
||||
|
|
|
@ -16,19 +16,20 @@ package terminal
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"android/soong/ui/status"
|
||||
)
|
||||
|
||||
type dumbStatusOutput struct {
|
||||
writer Writer
|
||||
writer io.Writer
|
||||
formatter formatter
|
||||
}
|
||||
|
||||
// NewDumbStatusOutput returns a StatusOutput that represents the
|
||||
// current build status similarly to Ninja's built-in terminal
|
||||
// output.
|
||||
func NewDumbStatusOutput(w Writer, formatter formatter) status.StatusOutput {
|
||||
func NewDumbStatusOutput(w io.Writer, formatter formatter) status.StatusOutput {
|
||||
return &dumbStatusOutput{
|
||||
writer: w,
|
||||
formatter: formatter,
|
||||
|
|
|
@ -16,6 +16,7 @@ package terminal
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
|
@ -23,7 +24,7 @@ import (
|
|||
)
|
||||
|
||||
type smartStatusOutput struct {
|
||||
writer Writer
|
||||
writer io.Writer
|
||||
formatter formatter
|
||||
|
||||
lock sync.Mutex
|
||||
|
@ -34,7 +35,7 @@ type smartStatusOutput struct {
|
|||
// NewSmartStatusOutput returns a StatusOutput that represents the
|
||||
// current build status similarly to Ninja's built-in terminal
|
||||
// output.
|
||||
func NewSmartStatusOutput(w Writer, formatter formatter) status.StatusOutput {
|
||||
func NewSmartStatusOutput(w io.Writer, formatter formatter) status.StatusOutput {
|
||||
return &smartStatusOutput{
|
||||
writer: w,
|
||||
formatter: formatter,
|
||||
|
@ -133,7 +134,7 @@ func (s *smartStatusOutput) statusLine(str string) {
|
|||
// Run this on every line in case the window has been resized while
|
||||
// we're printing. This could be optimized to only re-run when we get
|
||||
// SIGWINCH if it ever becomes too time consuming.
|
||||
if max, ok := s.writer.termWidth(); ok {
|
||||
if max, ok := termWidth(s.writer); ok {
|
||||
if len(str) > max {
|
||||
// TODO: Just do a max. Ninja elides the middle, but that's
|
||||
// more complicated and these lines aren't that important.
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
package terminal
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"android/soong/ui/status"
|
||||
)
|
||||
|
||||
|
@ -24,10 +26,10 @@ import (
|
|||
//
|
||||
// statusFormat takes nearly all the same options as NINJA_STATUS.
|
||||
// %c is currently unsupported.
|
||||
func NewStatusOutput(w Writer, statusFormat string, quietBuild bool) status.StatusOutput {
|
||||
func NewStatusOutput(w io.Writer, statusFormat string, quietBuild bool) status.StatusOutput {
|
||||
formatter := newFormatter(statusFormat, quietBuild)
|
||||
|
||||
if w.isSmartTerminal() {
|
||||
if isSmartTerminal(w) {
|
||||
return NewSmartStatusOutput(w, formatter)
|
||||
} else {
|
||||
return NewDumbStatusOutput(w, formatter)
|
||||
|
|
|
@ -89,17 +89,9 @@ func TestStatusOutput(t *testing.T) {
|
|||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Run("smart", func(t *testing.T) {
|
||||
smart := &fakeSmartTerminal{termWidth: 40}
|
||||
stdio := customStdio{
|
||||
stdin: nil,
|
||||
stdout: smart,
|
||||
stderr: nil,
|
||||
}
|
||||
|
||||
writer := NewWriter(stdio)
|
||||
stat := NewStatusOutput(writer, "", false)
|
||||
stat := NewStatusOutput(smart, "", false)
|
||||
tt.calls(stat)
|
||||
stat.Flush()
|
||||
writer.Finish()
|
||||
|
||||
if g, w := smart.String(), tt.smart; g != w {
|
||||
t.Errorf("want:\n%q\ngot:\n%q", w, g)
|
||||
|
@ -108,17 +100,9 @@ func TestStatusOutput(t *testing.T) {
|
|||
|
||||
t.Run("dumb", func(t *testing.T) {
|
||||
dumb := &bytes.Buffer{}
|
||||
stdio := customStdio{
|
||||
stdin: nil,
|
||||
stdout: dumb,
|
||||
stderr: nil,
|
||||
}
|
||||
|
||||
writer := NewWriter(stdio)
|
||||
stat := NewStatusOutput(writer, "", false)
|
||||
stat := NewStatusOutput(dumb, "", false)
|
||||
tt.calls(stat)
|
||||
stat.Flush()
|
||||
writer.Finish()
|
||||
|
||||
if g, w := dumb.String(), tt.dumb; g != w {
|
||||
t.Errorf("want:\n%q\ngot:\n%q", w, g)
|
||||
|
@ -267,15 +251,7 @@ func actionWithOuptutWithAnsiCodes(stat status.StatusOutput) {
|
|||
|
||||
func TestSmartStatusOutputWidthChange(t *testing.T) {
|
||||
smart := &fakeSmartTerminal{termWidth: 40}
|
||||
|
||||
stdio := customStdio{
|
||||
stdin: nil,
|
||||
stdout: smart,
|
||||
stderr: nil,
|
||||
}
|
||||
|
||||
writer := NewWriter(stdio)
|
||||
stat := NewStatusOutput(writer, "", false)
|
||||
stat := NewStatusOutput(smart, "", false)
|
||||
|
||||
runner := newRunner(stat, 2)
|
||||
|
||||
|
@ -287,7 +263,6 @@ func TestSmartStatusOutputWidthChange(t *testing.T) {
|
|||
runner.finishAction(result)
|
||||
|
||||
stat.Flush()
|
||||
writer.Finish()
|
||||
|
||||
w := "\r[ 0% 0/2] action with very long descrip\x1b[K\r[ 50% 1/2] action with very lo\x1b[K\n"
|
||||
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package terminal provides a set of interfaces that can be used to interact
|
||||
// with the terminal (including falling back when the terminal is detected to
|
||||
// be a redirect or other dumb terminal)
|
||||
package terminal
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// StdioInterface represents a set of stdin/stdout/stderr Reader/Writers
|
||||
type StdioInterface interface {
|
||||
Stdin() io.Reader
|
||||
Stdout() io.Writer
|
||||
Stderr() io.Writer
|
||||
}
|
||||
|
||||
// StdioImpl uses the OS stdin/stdout/stderr to implement StdioInterface
|
||||
type StdioImpl struct{}
|
||||
|
||||
func (StdioImpl) Stdin() io.Reader { return os.Stdin }
|
||||
func (StdioImpl) Stdout() io.Writer { return os.Stdout }
|
||||
func (StdioImpl) Stderr() io.Writer { return os.Stderr }
|
||||
|
||||
var _ StdioInterface = StdioImpl{}
|
||||
|
||||
type customStdio struct {
|
||||
stdin io.Reader
|
||||
stdout io.Writer
|
||||
stderr io.Writer
|
||||
}
|
||||
|
||||
func NewCustomStdio(stdin io.Reader, stdout, stderr io.Writer) StdioInterface {
|
||||
return customStdio{stdin, stdout, stderr}
|
||||
}
|
||||
|
||||
func (c customStdio) Stdin() io.Reader { return c.stdin }
|
||||
func (c customStdio) Stdout() io.Writer { return c.stdout }
|
||||
func (c customStdio) Stderr() io.Writer { return c.stderr }
|
||||
|
||||
var _ StdioInterface = customStdio{}
|
|
@ -1,122 +0,0 @@
|
|||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package terminal provides a set of interfaces that can be used to interact
|
||||
// with the terminal (including falling back when the terminal is detected to
|
||||
// be a redirect or other dumb terminal)
|
||||
package terminal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Writer provides an interface to write temporary and permanent messages to
|
||||
// the terminal.
|
||||
//
|
||||
// The terminal is considered to be a dumb terminal if TERM==dumb, or if a
|
||||
// terminal isn't detected on stdout/stderr (generally because it's a pipe or
|
||||
// file). Dumb terminals will strip out all ANSI escape sequences, including
|
||||
// colors.
|
||||
type Writer interface {
|
||||
// Print prints the string to the terminal, overwriting any current
|
||||
// status being displayed.
|
||||
//
|
||||
// On a dumb terminal, the status messages will be kept.
|
||||
Print(str string)
|
||||
|
||||
// Finish ensures that the output ends with a newline (preserving any
|
||||
// current status line that is current displayed).
|
||||
//
|
||||
// This does nothing on dumb terminals.
|
||||
Finish()
|
||||
|
||||
// Write implements the io.Writer interface. This is primarily so that
|
||||
// the logger can use this interface to print to stderr without
|
||||
// breaking the other semantics of this interface.
|
||||
//
|
||||
// Try to use any of the other functions if possible.
|
||||
Write(p []byte) (n int, err error)
|
||||
|
||||
isSmartTerminal() bool
|
||||
termWidth() (int, bool)
|
||||
}
|
||||
|
||||
// NewWriter creates a new Writer based on the stdio and the TERM
|
||||
// environment variable.
|
||||
func NewWriter(stdio StdioInterface) Writer {
|
||||
w := &writerImpl{
|
||||
stdio: stdio,
|
||||
}
|
||||
|
||||
return w
|
||||
}
|
||||
|
||||
type writerImpl struct {
|
||||
stdio StdioInterface
|
||||
}
|
||||
|
||||
func (w *writerImpl) Print(str string) {
|
||||
fmt.Fprint(w.stdio.Stdout(), str)
|
||||
if len(str) == 0 || str[len(str)-1] != '\n' {
|
||||
fmt.Fprint(w.stdio.Stdout(), "\n")
|
||||
}
|
||||
}
|
||||
|
||||
func (w *writerImpl) Finish() {}
|
||||
|
||||
func (w *writerImpl) Write(p []byte) (n int, err error) {
|
||||
return w.stdio.Stdout().Write(p)
|
||||
}
|
||||
|
||||
func (w *writerImpl) isSmartTerminal() bool {
|
||||
return isSmartTerminal(w.stdio.Stdout())
|
||||
}
|
||||
|
||||
func (w *writerImpl) termWidth() (int, bool) {
|
||||
return termWidth(w.stdio.Stdout())
|
||||
}
|
||||
|
||||
// StdioInterface represents a set of stdin/stdout/stderr Reader/Writers
|
||||
type StdioInterface interface {
|
||||
Stdin() io.Reader
|
||||
Stdout() io.Writer
|
||||
Stderr() io.Writer
|
||||
}
|
||||
|
||||
// StdioImpl uses the OS stdin/stdout/stderr to implement StdioInterface
|
||||
type StdioImpl struct{}
|
||||
|
||||
func (StdioImpl) Stdin() io.Reader { return os.Stdin }
|
||||
func (StdioImpl) Stdout() io.Writer { return os.Stdout }
|
||||
func (StdioImpl) Stderr() io.Writer { return os.Stderr }
|
||||
|
||||
var _ StdioInterface = StdioImpl{}
|
||||
|
||||
type customStdio struct {
|
||||
stdin io.Reader
|
||||
stdout io.Writer
|
||||
stderr io.Writer
|
||||
}
|
||||
|
||||
func NewCustomStdio(stdin io.Reader, stdout, stderr io.Writer) StdioInterface {
|
||||
return customStdio{stdin, stdout, stderr}
|
||||
}
|
||||
|
||||
func (c customStdio) Stdin() io.Reader { return c.stdin }
|
||||
func (c customStdio) Stdout() io.Writer { return c.stdout }
|
||||
func (c customStdio) Stderr() io.Writer { return c.stderr }
|
||||
|
||||
var _ StdioInterface = customStdio{}
|
Loading…
Reference in New Issue