| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2017 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. |
| 4 |
| 5 package vpython |
| 6 |
| 7 import ( |
| 8 "github.com/luci/luci-go/common/errors" |
| 9 "github.com/luci/luci-go/common/system/environ" |
| 10 |
| 11 "golang.org/x/net/context" |
| 12 ) |
| 13 |
| 14 var ( |
| 15 // EnvSpecPath is the exported enviornment variable for the specificatio
n path. |
| 16 // |
| 17 // This is added to the bootstrap enviornment used by Run to allow subpr
ocess |
| 18 // "vpython" invocations to automatically inherit the same environment. |
| 19 EnvSpecPath = "VPYTHON_VENV_SPEC_PATH" |
| 20 ) |
| 21 |
| 22 // Run sets up a Python VirtualEnv and executes the supplied Options. |
| 23 // |
| 24 // Run returns nil if if the Python environment was successfully set-up and the |
| 25 // Python interpreter was successfully run with a zero return code. If the |
| 26 // Python interpreter returns a non-zero return code, a PythonError (potentially |
| 27 // wrapped) will be returned. |
| 28 // |
| 29 // A generalized return code to return for an error value can be obtained via |
| 30 // ReturnCode. |
| 31 // |
| 32 // Run consists of: |
| 33 // |
| 34 // - Identify the target Python script to run (if there is one). |
| 35 // - Identifying the Python interpreter to use. |
| 36 // - Composing the environment specification. |
| 37 // - Constructing the virtual environment (download, install). |
| 38 // - Execute the Python process with the supplied arguments. |
| 39 // |
| 40 // The Python subprocess is bound to the lifetime of ctx, and will be terminated |
| 41 // if ctx is cancelled. |
| 42 func Run(c context.Context, opts Options) error { |
| 43 // Resolve our Options. |
| 44 if err := opts.resolve(c); err != nil { |
| 45 return errors.Annotate(err).Reason("could not resolve options").
Err() |
| 46 } |
| 47 |
| 48 // Create our virtual enviornment root directory. |
| 49 venv, err := opts.EnvConfig.Env(c) |
| 50 if err != nil { |
| 51 return errors.Annotate(err).Reason("failed to resolve VirtualEnv
").Err() |
| 52 } |
| 53 if err := venv.Setup(c, opts.WaitForEnv); err != nil { |
| 54 return errors.Annotate(err).Reason("failed to setup VirtualEnv")
.Err() |
| 55 } |
| 56 |
| 57 // Build the augmented environment variables. |
| 58 e := opts.Environ |
| 59 if e.Len() == 0 { |
| 60 // If no environment was supplied, use the system environment. |
| 61 e = environ.System() |
| 62 } |
| 63 e.Set("VIRTUAL_ENV", venv.Root) // Set by VirtualEnv script. |
| 64 if venv.SpecPath != "" { |
| 65 e.Set(EnvSpecPath, venv.SpecPath) |
| 66 } |
| 67 |
| 68 // Run our bootstrapped Python command. |
| 69 cmd := venv.InterpreterCommand() |
| 70 cmd.WorkDir = opts.WorkDir |
| 71 cmd.Isolated = true |
| 72 cmd.ConnectSTDIN = true |
| 73 cmd.Env = e.Sorted() |
| 74 if err := cmd.Run(c, opts.Args...); err != nil { |
| 75 return errors.Annotate(err).Reason("failed to execute Python boo
tstrap").Err() |
| 76 } |
| 77 return nil |
| 78 } |
| OLD | NEW |