Force dumpvars into dumb terminal mode and move log files

Force soong_ui in dumpvars mode to use a dumb terminal so that it
doesn't print an empty status table.  Also move the logs to files
that are prefixed with "dumpvars-" so that they don't rotate the
real build logs.

Fixes: 139307849
Test: lunch
Change-Id: If92421af07731fedc9ca42670f309e95922a2224
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index 1171a65..2800ade 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -158,7 +158,7 @@
 func main() {
 	stdio := terminal.StdioImpl{}
 
-	output := terminal.NewStatusOutput(stdio.Stdout(), "",
+	output := terminal.NewStatusOutput(stdio.Stdout(), "", false,
 		build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"))
 
 	log := logger.New(output)
@@ -391,7 +391,7 @@
 		Thread:  mpctx.Tracer.NewThread(product),
 		Status:  &status.Status{},
 	}}
-	ctx.Status.AddOutput(terminal.NewStatusOutput(ctx.Writer, "",
+	ctx.Status.AddOutput(terminal.NewStatusOutput(ctx.Writer, "", false,
 		build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD")))
 
 	config := build.NewConfig(ctx, flag.Args()...)
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index ec4f90e..974c644 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -41,6 +41,12 @@
 	// description for the flag (to display when running help)
 	description string
 
+	// Forces the status output into dumb terminal mode.
+	forceDumbOutput bool
+
+	// Sets a prefix string to use for filenames of log files.
+	logsPrefix string
+
 	// Creates the build configuration based on the args and build context.
 	config func(ctx build.Context, args ...string) build.Config
 
@@ -64,17 +70,21 @@
 		stdio: stdio,
 		run:   make,
 	}, {
-		flag:        "--dumpvar-mode",
-		description: "print the value of the legacy make variable VAR to stdout",
-		config:      dumpVarConfig,
-		stdio:       customStdio,
-		run:         dumpVar,
+		flag:            "--dumpvar-mode",
+		description:     "print the value of the legacy make variable VAR to stdout",
+		forceDumbOutput: true,
+		logsPrefix:      "dumpvars-",
+		config:          dumpVarConfig,
+		stdio:           customStdio,
+		run:             dumpVar,
 	}, {
-		flag:        "--dumpvars-mode",
-		description: "dump the values of one or more legacy make variables, in shell syntax",
-		config:      dumpVarConfig,
-		stdio:       customStdio,
-		run:         dumpVars,
+		flag:            "--dumpvars-mode",
+		description:     "dump the values of one or more legacy make variables, in shell syntax",
+		forceDumbOutput: true,
+		logsPrefix:      "dumpvars-",
+		config:          dumpVarConfig,
+		stdio:           customStdio,
+		run:             dumpVars,
 	}, {
 		flag:        "--build-mode",
 		description: "build modules based on the specified build action",
@@ -113,7 +123,7 @@
 		os.Exit(1)
 	}
 
-	output := terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"),
+	output := terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"), c.forceDumbOutput,
 		build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"))
 
 	log := logger.New(output)
@@ -157,14 +167,14 @@
 	}
 
 	os.MkdirAll(logsDir, 0777)
-	log.SetOutput(filepath.Join(logsDir, "soong.log"))
-	trace.SetOutput(filepath.Join(logsDir, "build.trace"))
-	stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, "verbose.log")))
-	stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, "error.log")))
-	stat.AddOutput(status.NewProtoErrorLog(log, filepath.Join(logsDir, "build_error")))
+	log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
+	trace.SetOutput(filepath.Join(logsDir, c.logsPrefix+"build.trace"))
+	stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, c.logsPrefix+"verbose.log")))
+	stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"error.log")))
+	stat.AddOutput(status.NewProtoErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"build_error")))
 	stat.AddOutput(status.NewCriticalPath(log))
 
-	defer met.Dump(filepath.Join(logsDir, "soong_metrics"))
+	defer met.Dump(filepath.Join(logsDir, c.logsPrefix+"soong_metrics"))
 
 	if start, ok := os.LookupEnv("TRACE_BEGIN_SOONG"); ok {
 		if !strings.HasSuffix(start, "N") {
diff --git a/ui/terminal/status.go b/ui/terminal/status.go
index 69a2a09..60dfc70 100644
--- a/ui/terminal/status.go
+++ b/ui/terminal/status.go
@@ -26,10 +26,10 @@
 //
 // statusFormat takes nearly all the same options as NINJA_STATUS.
 // %c is currently unsupported.
-func NewStatusOutput(w io.Writer, statusFormat string, quietBuild bool) status.StatusOutput {
+func NewStatusOutput(w io.Writer, statusFormat string, forceDumbOutput, quietBuild bool) status.StatusOutput {
 	formatter := newFormatter(statusFormat, quietBuild)
 
-	if isSmartTerminal(w) {
+	if !forceDumbOutput && isSmartTerminal(w) {
 		return NewSmartStatusOutput(w, formatter)
 	} else {
 		return NewDumbStatusOutput(w, formatter)
diff --git a/ui/terminal/status_test.go b/ui/terminal/status_test.go
index 81aa238..9f60829 100644
--- a/ui/terminal/status_test.go
+++ b/ui/terminal/status_test.go
@@ -94,7 +94,7 @@
 
 			t.Run("smart", func(t *testing.T) {
 				smart := &fakeSmartTerminal{termWidth: 40}
-				stat := NewStatusOutput(smart, "", false)
+				stat := NewStatusOutput(smart, "", false, false)
 				tt.calls(stat)
 				stat.Flush()
 
@@ -105,7 +105,7 @@
 
 			t.Run("dumb", func(t *testing.T) {
 				dumb := &bytes.Buffer{}
-				stat := NewStatusOutput(dumb, "", false)
+				stat := NewStatusOutput(dumb, "", false, false)
 				tt.calls(stat)
 				stat.Flush()
 
@@ -113,6 +113,17 @@
 					t.Errorf("want:\n%q\ngot:\n%q", w, g)
 				}
 			})
+
+			t.Run("force dumb", func(t *testing.T) {
+				smart := &fakeSmartTerminal{termWidth: 40}
+				stat := NewStatusOutput(smart, "", true, false)
+				tt.calls(stat)
+				stat.Flush()
+
+				if g, w := smart.String(), tt.dumb; g != w {
+					t.Errorf("want:\n%q\ngot:\n%q", w, g)
+				}
+			})
 		})
 	}
 }
@@ -258,7 +269,7 @@
 	os.Setenv(tableHeightEnVar, "")
 
 	smart := &fakeSmartTerminal{termWidth: 40}
-	stat := NewStatusOutput(smart, "", false)
+	stat := NewStatusOutput(smart, "", false, false)
 	smartStat := stat.(*smartStatusOutput)
 	smartStat.sigwinchHandled = make(chan bool)