blob: 146704e01df80403f0c3a6fe9cfe51d35dbcbcce [file] [log] [blame]
// Copyright 2017 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Package main implements the tast executable, used to build and run tests.
package main
import (
"context"
"flag"
"fmt"
"os"
"github.com/google/subcommands"
"golang.org/x/crypto/ssh/terminal"
"go.chromium.org/tast/core/internal/command"
"go.chromium.org/tast/core/internal/logging"
)
// Version is the version info of this command. It is filled in during emerge.
var Version = "<unknown>"
// newLogger creates a logging.Logger based on the supplied command-line flags.
func newLogger(verbose, logTime bool) *logging.SinkLogger {
level := logging.LevelInfo
if verbose {
level = logging.LevelDebug
}
return logging.NewSinkLogger(level, logTime, logging.NewWriterSink(os.Stdout))
}
// installSignalHandler starts a goroutine that attempts to do some minimal
// cleanup when the process is being terminated by a signal (which prevents
// deferred functions from running).
func installSignalHandler(ctx context.Context) {
var st *terminal.State
fd := int(os.Stdin.Fd())
if terminal.IsTerminal(fd) {
var err error
if st, err = terminal.GetState(fd); err != nil {
logging.Info(ctx, "Failed to get terminal state: ", err)
}
}
command.InstallSignalHandler(os.Stderr, func(os.Signal) {
if st != nil {
terminal.Restore(fd, st)
}
})
}
// doMain implements the main body of the program. It's a separate function so
// that its deferred functions will run before os.Exit makes the program exit
// immediately.
func doMain() int {
subcommands.Register(subcommands.HelpCommand(), "")
subcommands.Register(subcommands.FlagsCommand(), "")
subcommands.Register(subcommands.CommandsCommand(), "")
subcommands.Register(newListCmd(os.Stdout, trunkDir()), "")
subcommands.Register(newRunCmd(trunkDir(), Version), "")
subcommands.Register(&symbolizeCmd{}, "")
subcommands.Register(newGlobalRuntimeVarsCmd(os.Stdout, trunkDir()), "")
version := flag.Bool("version", false, "print version and exit")
verbose := flag.Bool("verbose", false, "use verbose logging")
logTime := flag.Bool("logtime", true, "include date/time headers in logs")
flag.Parse()
if *version {
fmt.Printf("tast version %s\n", Version)
return 0
}
logger := newLogger(*verbose, *logTime)
ctx := logging.AttachLogger(context.Background(), logger)
installSignalHandler(ctx)
return int(subcommands.Execute(ctx))
}
func main() {
os.Exit(doMain())
}