Home | History | Annotate | Download | only in build
      1 // Copyright 2017 Google Inc. All rights reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 package build
     16 
     17 import (
     18 	"context"
     19 	"io"
     20 	"os"
     21 	"time"
     22 
     23 	"android/soong/ui/logger"
     24 	"android/soong/ui/tracer"
     25 )
     26 
     27 type StdioInterface interface {
     28 	Stdin() io.Reader
     29 	Stdout() io.Writer
     30 	Stderr() io.Writer
     31 }
     32 
     33 type StdioImpl struct{}
     34 
     35 func (StdioImpl) Stdin() io.Reader  { return os.Stdin }
     36 func (StdioImpl) Stdout() io.Writer { return os.Stdout }
     37 func (StdioImpl) Stderr() io.Writer { return os.Stderr }
     38 
     39 var _ StdioInterface = StdioImpl{}
     40 
     41 type customStdio struct {
     42 	stdin  io.Reader
     43 	stdout io.Writer
     44 	stderr io.Writer
     45 }
     46 
     47 func NewCustomStdio(stdin io.Reader, stdout, stderr io.Writer) StdioInterface {
     48 	return customStdio{stdin, stdout, stderr}
     49 }
     50 
     51 func (c customStdio) Stdin() io.Reader  { return c.stdin }
     52 func (c customStdio) Stdout() io.Writer { return c.stdout }
     53 func (c customStdio) Stderr() io.Writer { return c.stderr }
     54 
     55 var _ StdioInterface = customStdio{}
     56 
     57 // Context combines a context.Context, logger.Logger, and StdIO redirection.
     58 // These all are agnostic of the current build, and may be used for multiple
     59 // builds, while the Config objects contain per-build information.
     60 type Context struct{ *ContextImpl }
     61 type ContextImpl struct {
     62 	context.Context
     63 	logger.Logger
     64 
     65 	StdioInterface
     66 
     67 	Thread tracer.Thread
     68 	Tracer tracer.Tracer
     69 }
     70 
     71 // BeginTrace starts a new Duration Event.
     72 func (c ContextImpl) BeginTrace(name string) {
     73 	if c.Tracer != nil {
     74 		c.Tracer.Begin(name, c.Thread)
     75 	}
     76 }
     77 
     78 // EndTrace finishes the last Duration Event.
     79 func (c ContextImpl) EndTrace() {
     80 	if c.Tracer != nil {
     81 		c.Tracer.End(c.Thread)
     82 	}
     83 }
     84 
     85 // CompleteTrace writes a trace with a beginning and end times.
     86 func (c ContextImpl) CompleteTrace(name string, begin, end uint64) {
     87 	if c.Tracer != nil {
     88 		c.Tracer.Complete(name, c.Thread, begin, end)
     89 	}
     90 }
     91 
     92 // ImportNinjaLog imports a .ninja_log file into the tracer.
     93 func (c ContextImpl) ImportNinjaLog(filename string, startOffset time.Time) {
     94 	if c.Tracer != nil {
     95 		c.Tracer.ImportNinjaLog(c.Thread, filename, startOffset)
     96 	}
     97 }
     98 
     99 func (c ContextImpl) IsTerminal() bool {
    100 	if term, ok := os.LookupEnv("TERM"); ok {
    101 		return term != "dumb" && isTerminal(c.Stdout()) && isTerminal(c.Stderr())
    102 	}
    103 	return false
    104 }
    105 
    106 func (c ContextImpl) IsErrTerminal() bool {
    107 	if term, ok := os.LookupEnv("TERM"); ok {
    108 		return term != "dumb" && isTerminal(c.Stderr())
    109 	}
    110 	return false
    111 }
    112 
    113 func (c ContextImpl) TermWidth() (int, bool) {
    114 	return termWidth(c.Stdout())
    115 }
    116