v.io/jiri@v0.0.0-20160715023856-abfb8b131290/tool/context.go (about)

     1  // Copyright 2015 The Vanadium Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package tool
     6  
     7  import (
     8  	"io"
     9  	"net/url"
    10  	"os"
    11  
    12  	"v.io/jiri/gerrit"
    13  	"v.io/jiri/jenkins"
    14  	"v.io/jiri/runutil"
    15  	"v.io/x/lib/cmdline"
    16  	"v.io/x/lib/envvar"
    17  	"v.io/x/lib/timing"
    18  )
    19  
    20  // Context represents an execution context of a tool command
    21  // invocation. Its purpose is to enable sharing of state throughout
    22  // the lifetime of a command invocation.
    23  type Context struct {
    24  	opts ContextOpts
    25  }
    26  
    27  // ContextOpts records the context options.
    28  type ContextOpts struct {
    29  	Color    *bool
    30  	Manifest *string
    31  	Env      map[string]string
    32  	Stdin    io.Reader
    33  	Stdout   io.Writer
    34  	Stderr   io.Writer
    35  	Verbose  *bool
    36  	Timer    *timing.Timer
    37  }
    38  
    39  // newContextOpts is the ContextOpts factory.
    40  func newContextOpts() *ContextOpts {
    41  	return &ContextOpts{
    42  		Color:    &ColorFlag,
    43  		Env:      map[string]string{},
    44  		Manifest: &ManifestFlag,
    45  		Stdin:    os.Stdin,
    46  		Stdout:   os.Stdout,
    47  		Stderr:   os.Stderr,
    48  		Verbose:  &VerboseFlag,
    49  		Timer:    nil,
    50  	}
    51  }
    52  
    53  // initOpts initializes all unset options to the given defaults.
    54  func initOpts(defaultOpts, opts *ContextOpts) {
    55  	if opts.Color == nil {
    56  		opts.Color = defaultOpts.Color
    57  	}
    58  	if opts.Env == nil {
    59  		opts.Env = defaultOpts.Env
    60  	}
    61  	if opts.Manifest == nil {
    62  		opts.Manifest = defaultOpts.Manifest
    63  	}
    64  	if opts.Stdin == nil {
    65  		opts.Stdin = defaultOpts.Stdin
    66  	}
    67  	if opts.Stdout == nil {
    68  		opts.Stdout = defaultOpts.Stdout
    69  	}
    70  	if opts.Stderr == nil {
    71  		opts.Stderr = defaultOpts.Stderr
    72  	}
    73  	if opts.Verbose == nil {
    74  		opts.Verbose = defaultOpts.Verbose
    75  	}
    76  	if opts.Timer == nil {
    77  		opts.Timer = defaultOpts.Timer
    78  	}
    79  }
    80  
    81  // NewContext is the Context factory.
    82  func NewContext(opts ContextOpts) *Context {
    83  	initOpts(newContextOpts(), &opts)
    84  	return &Context{opts: opts}
    85  }
    86  
    87  // NewContextFromEnv returns a new context instance based on the given
    88  // cmdline environment.
    89  func NewContextFromEnv(env *cmdline.Env) *Context {
    90  	opts := ContextOpts{}
    91  	initOpts(newContextOpts(), &opts)
    92  	opts.Env = envvar.CopyMap(env.Vars)
    93  	opts.Stdin = env.Stdin
    94  	opts.Stdout = env.Stdout
    95  	opts.Stderr = env.Stderr
    96  	opts.Timer = env.Timer
    97  	return NewContext(opts)
    98  }
    99  
   100  // NewDefaultContext returns a new default context.
   101  func NewDefaultContext() *Context {
   102  	return NewContext(ContextOpts{})
   103  }
   104  
   105  // Clone creates a clone of the given context, overriding select
   106  // settings using the given options.
   107  func (ctx Context) Clone(opts ContextOpts) *Context {
   108  	initOpts(&ctx.opts, &opts)
   109  	return NewContext(opts)
   110  }
   111  
   112  // Color returns the color setting of the context.
   113  func (ctx Context) Color() bool {
   114  	return *ctx.opts.Color
   115  }
   116  
   117  // Env returns the environment of the context.
   118  func (ctx Context) Env() map[string]string {
   119  	return ctx.opts.Env
   120  }
   121  
   122  // Gerrit returns the Gerrit instance of the context.
   123  func (ctx Context) Gerrit(host *url.URL) *gerrit.Gerrit {
   124  	return gerrit.New(ctx.NewSeq(), host)
   125  }
   126  
   127  // Jenkins returns a new Jenkins instance that can be used to
   128  // communicate with a Jenkins server running at the given host.
   129  func (ctx Context) Jenkins(host string) (*jenkins.Jenkins, error) {
   130  	return jenkins.New(host)
   131  }
   132  
   133  // Manifest returns the manifest of the context.
   134  func (ctx Context) Manifest() string {
   135  	return *ctx.opts.Manifest
   136  }
   137  
   138  // NewSeq returns a new instance of Sequence initialized using the options
   139  // stored in the context.
   140  func (ctx Context) NewSeq() runutil.Sequence {
   141  	return runutil.NewSequence(ctx.opts.Env, ctx.opts.Stdin, ctx.opts.Stdout, ctx.opts.Stderr, *ctx.opts.Color, *ctx.opts.Verbose)
   142  }
   143  
   144  // Stdin returns the standard input of the context.
   145  func (ctx Context) Stdin() io.Reader {
   146  	return ctx.opts.Stdin
   147  }
   148  
   149  // Stdout returns the standard output of the context.
   150  func (ctx Context) Stdout() io.Writer {
   151  	return ctx.opts.Stdout
   152  }
   153  
   154  // Stderr returns the standard error output of the context.
   155  func (ctx Context) Stderr() io.Writer {
   156  	return ctx.opts.Stderr
   157  }
   158  
   159  // Verbose returns the verbosity setting of the context.
   160  func (ctx Context) Verbose() bool {
   161  	return *ctx.opts.Verbose
   162  }
   163  
   164  // Timer returns the timer associated with the context, which may be nil.
   165  func (ctx Context) Timer() *timing.Timer {
   166  	return ctx.opts.Timer
   167  }
   168  
   169  // TimerPush calls ctx.Timer().Push(name), only if the Timer is non-nil.
   170  func (ctx Context) TimerPush(name string) {
   171  	if ctx.opts.Timer != nil {
   172  		ctx.opts.Timer.Push(name)
   173  	}
   174  }
   175  
   176  // TimerPop calls ctx.Timer().Pop(), only if the Timer is non-nil.
   177  func (ctx Context) TimerPop() {
   178  	if ctx.opts.Timer != nil {
   179  		ctx.opts.Timer.Pop()
   180  	}
   181  }