blob: cd62cf9cbaa119277a9a9928ecda257773bfbc55 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package tool
import (
"io"
"os"
"go.fuchsia.dev/jiri/cmdline"
"go.fuchsia.dev/jiri/envvar"
"go.fuchsia.dev/jiri/timing"
)
// Context represents an execution context of a tool command
// invocation. Its purpose is to enable sharing of state throughout
// the lifetime of a command invocation.
type Context struct {
opts ContextOpts
}
// ContextOpts records the context options.
type ContextOpts struct {
Env map[string]string
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
Timer *timing.Timer
}
// newContextOpts is the ContextOpts factory.
func newContextOpts() *ContextOpts {
return &ContextOpts{
Env: map[string]string{},
Stdin: os.Stdin,
Stdout: os.Stdout,
Stderr: os.Stderr,
Timer: nil,
}
}
// initOpts initializes all unset options to the given defaults.
func initOpts(defaultOpts, opts *ContextOpts) {
if opts.Env == nil {
opts.Env = defaultOpts.Env
}
if opts.Stdin == nil {
opts.Stdin = defaultOpts.Stdin
}
if opts.Stdout == nil {
opts.Stdout = defaultOpts.Stdout
}
if opts.Stderr == nil {
opts.Stderr = defaultOpts.Stderr
}
if opts.Timer == nil {
opts.Timer = defaultOpts.Timer
}
}
// NewContext is the Context factory.
func NewContext(opts ContextOpts) *Context {
initOpts(newContextOpts(), &opts)
return &Context{opts: opts}
}
// NewContextFromEnv returns a new context instance based on the given
// cmdline environment.
func NewContextFromEnv(env *cmdline.Env) *Context {
opts := ContextOpts{}
initOpts(newContextOpts(), &opts)
opts.Env = envvar.CopyMap(env.Vars)
opts.Stdin = env.Stdin
opts.Stdout = env.Stdout
opts.Stderr = env.Stderr
opts.Timer = env.Timer
return NewContext(opts)
}
// NewDefaultContext returns a new default context.
func NewDefaultContext() *Context {
return NewContext(ContextOpts{})
}
// Clone creates a clone of the given context, overriding select
// settings using the given options.
func (ctx Context) Clone(opts ContextOpts) *Context {
initOpts(&ctx.opts, &opts)
return NewContext(opts)
}
// Env returns the environment of the context.
func (ctx Context) Env() map[string]string {
return ctx.opts.Env
}
// Stdin returns the standard input of the context.
func (ctx Context) Stdin() io.Reader {
return ctx.opts.Stdin
}
// Stdout returns the standard output of the context.
func (ctx Context) Stdout() io.Writer {
return ctx.opts.Stdout
}
// Stderr returns the standard error output of the context.
func (ctx Context) Stderr() io.Writer {
return ctx.opts.Stderr
}
// Timer returns the timer associated with the context, which may be nil.
func (ctx Context) Timer() *timing.Timer {
return ctx.opts.Timer
}
// TimerPush calls ctx.Timer().Push(name), only if the Timer is non-nil.
func (ctx Context) TimerPush(name string) {
if ctx.opts.Timer != nil {
ctx.opts.Timer.Push(name)
}
}
// TimerPop calls ctx.Timer().Pop(), only if the Timer is non-nil.
func (ctx Context) TimerPop() {
if ctx.opts.Timer != nil {
ctx.opts.Timer.Pop()
}
}