OLD | NEW |
1 // Copyright 2017 The LUCI Authors. All rights reserved. | 1 // Copyright 2017 The LUCI Authors. All rights reserved. |
2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
4 | 4 |
5 package application | 5 package application |
6 | 6 |
7 import ( | 7 import ( |
8 "flag" | 8 "flag" |
9 "fmt" | 9 "fmt" |
10 "io/ioutil" | 10 "io/ioutil" |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 a.logConfig.AddFlags(fs) | 160 a.logConfig.AddFlags(fs) |
161 } | 161 } |
162 | 162 |
163 func (a *application) mainImpl(c context.Context, argv0 string, args []string) e
rror { | 163 func (a *application) mainImpl(c context.Context, argv0 string, args []string) e
rror { |
164 // Determine our VirtualEnv base directory. | 164 // Determine our VirtualEnv base directory. |
165 if v, ok := a.opts.Environ.Get(VirtualEnvRootENV); ok { | 165 if v, ok := a.opts.Environ.Get(VirtualEnvRootENV); ok { |
166 a.opts.EnvConfig.BaseDir = v | 166 a.opts.EnvConfig.BaseDir = v |
167 } else { | 167 } else { |
168 hdir, err := homedir.Dir() | 168 hdir, err := homedir.Dir() |
169 if err != nil { | 169 if err != nil { |
170 » » » return errors.Annotate(err).Reason("failed to get user h
ome directory").Err() | 170 » » » return errors.Annotate(err, "failed to get user home dir
ectory").Err() |
171 } | 171 } |
172 a.opts.EnvConfig.BaseDir = filepath.Join(hdir, ".vpython") | 172 a.opts.EnvConfig.BaseDir = filepath.Join(hdir, ".vpython") |
173 } | 173 } |
174 | 174 |
175 // Extract "vpython" arguments and parse them. | 175 // Extract "vpython" arguments and parse them. |
176 fs := flag.NewFlagSet("", flag.ExitOnError) | 176 fs := flag.NewFlagSet("", flag.ExitOnError) |
177 fs.SetOutput(os.Stdout) // Python uses STDOUT for help and flag informat
ion. | 177 fs.SetOutput(os.Stdout) // Python uses STDOUT for help and flag informat
ion. |
178 | 178 |
179 a.addToFlagSet(fs) | 179 a.addToFlagSet(fs) |
180 selfArgs, args := extractFlagsForSet(args, fs) | 180 selfArgs, args := extractFlagsForSet(args, fs) |
181 if err := fs.Parse(selfArgs); err != nil && err != flag.ErrHelp { | 181 if err := fs.Parse(selfArgs); err != nil && err != flag.ErrHelp { |
182 » » return errors.Annotate(err).Reason("failed to parse flags").Err(
) | 182 » » return errors.Annotate(err, "failed to parse flags").Err() |
183 } | 183 } |
184 | 184 |
185 // Identify the "self" executable. Use this to construct a "lookPath", w
hich | 185 // Identify the "self" executable. Use this to construct a "lookPath", w
hich |
186 // will be used to locate the base Python interpreter. | 186 // will be used to locate the base Python interpreter. |
187 lp := lookPath{ | 187 lp := lookPath{ |
188 probeBase: prober.Probe{ | 188 probeBase: prober.Probe{ |
189 RelativePathOverride: a.RelativePathOverride, | 189 RelativePathOverride: a.RelativePathOverride, |
190 }, | 190 }, |
191 env: a.opts.Environ, | 191 env: a.opts.Environ, |
192 } | 192 } |
(...skipping 10 matching lines...) Expand all Loading... |
203 | 203 |
204 // If an spec path was manually specified, load and use it. | 204 // If an spec path was manually specified, load and use it. |
205 if a.specPath != "" { | 205 if a.specPath != "" { |
206 var sp vpythonAPI.Spec | 206 var sp vpythonAPI.Spec |
207 if err := spec.Load(a.specPath, &sp); err != nil { | 207 if err := spec.Load(a.specPath, &sp); err != nil { |
208 return err | 208 return err |
209 } | 209 } |
210 a.opts.EnvConfig.Spec = &sp | 210 a.opts.EnvConfig.Spec = &sp |
211 } else if specPath := a.opts.Environ.GetEmpty(DefaultSpecENV); specPath
!= "" { | 211 } else if specPath := a.opts.Environ.GetEmpty(DefaultSpecENV); specPath
!= "" { |
212 if err := spec.Load(specPath, &a.opts.DefaultSpec); err != nil { | 212 if err := spec.Load(specPath, &a.opts.DefaultSpec); err != nil { |
213 » » » return errors.Annotate(err). | 213 » » » return errors.Annotate(err, "failed to load default spec
ification file (%s) from %s", |
214 » » » » Reason("failed to load default specification fil
e ("+DefaultSpecENV+"from: %(path)s"). | 214 » » » » DefaultSpecENV, specPath).Err() |
215 » » » » D("path", specPath). | |
216 » » » » Err() | |
217 } | 215 } |
218 } | 216 } |
219 | 217 |
220 // If an empty BaseDir was specified, use a temporary directory and clea
n it | 218 // If an empty BaseDir was specified, use a temporary directory and clea
n it |
221 // up on completion. | 219 // up on completion. |
222 if a.opts.EnvConfig.BaseDir == "" { | 220 if a.opts.EnvConfig.BaseDir == "" { |
223 tdir, err := ioutil.TempDir("", "vpython") | 221 tdir, err := ioutil.TempDir("", "vpython") |
224 if err != nil { | 222 if err != nil { |
225 » » » return errors.Annotate(err).Reason("failed to create tem
porary directory").Err() | 223 » » » return errors.Annotate(err, "failed to create temporary
directory").Err() |
226 } | 224 } |
227 defer func() { | 225 defer func() { |
228 logging.Debugf(c, "Removing temporary directory: %s", td
ir) | 226 logging.Debugf(c, "Removing temporary directory: %s", td
ir) |
229 if terr := filesystem.RemoveAll(tdir); terr != nil { | 227 if terr := filesystem.RemoveAll(tdir); terr != nil { |
230 logging.WithError(terr).Warningf(c, "Failed to c
lean up temporary directory; leaking: %s", tdir) | 228 logging.WithError(terr).Warningf(c, "Failed to c
lean up temporary directory; leaking: %s", tdir) |
231 } | 229 } |
232 }() | 230 }() |
233 a.opts.EnvConfig.BaseDir = tdir | 231 a.opts.EnvConfig.BaseDir = tdir |
234 } | 232 } |
235 | 233 |
236 // Development mode (subcommands). | 234 // Development mode (subcommands). |
237 if a.devMode { | 235 if a.devMode { |
238 return a.mainDev(c, args) | 236 return a.mainDev(c, args) |
239 } | 237 } |
240 | 238 |
241 a.opts.Args = args | 239 a.opts.Args = args |
242 if err := vpython.Run(c, a.opts); err != nil { | 240 if err := vpython.Run(c, a.opts); err != nil { |
243 // If the process failed because of a non-zero return value, ret
urn that | 241 // If the process failed because of a non-zero return value, ret
urn that |
244 // as our error. | 242 // as our error. |
245 if rc, has := exitcode.Get(errors.Unwrap(err)); has { | 243 if rc, has := exitcode.Get(errors.Unwrap(err)); has { |
246 err = ReturnCodeError(rc) | 244 err = ReturnCodeError(rc) |
247 } | 245 } |
248 | 246 |
249 » » return errors.Annotate(err).Err() | 247 » » return errors.Annotate(err, "").Err() |
250 } | 248 } |
251 return nil | 249 return nil |
252 } | 250 } |
253 | 251 |
254 func (a *application) showPythonHelp(c context.Context, fs *flag.FlagSet, lp *lo
okPath) error { | 252 func (a *application) showPythonHelp(c context.Context, fs *flag.FlagSet, lp *lo
okPath) error { |
255 self, err := os.Executable() | 253 self, err := os.Executable() |
256 if err != nil { | 254 if err != nil { |
257 self = "vpython" | 255 self = "vpython" |
258 } | 256 } |
259 vers, err := cipdVersion.GetStartupVersion() | 257 vers, err := cipdVersion.GetStartupVersion() |
260 if err == nil && vers.PackageName != "" && vers.InstanceID != "" { | 258 if err == nil && vers.PackageName != "" && vers.InstanceID != "" { |
261 self = fmt.Sprintf("%s (%s@%s)", self, vers.PackageName, vers.In
stanceID) | 259 self = fmt.Sprintf("%s (%s@%s)", self, vers.PackageName, vers.In
stanceID) |
262 } | 260 } |
263 | 261 |
264 fmt.Fprintf(os.Stdout, "Usage of %s:\n", self) | 262 fmt.Fprintf(os.Stdout, "Usage of %s:\n", self) |
265 fs.SetOutput(os.Stdout) | 263 fs.SetOutput(os.Stdout) |
266 fs.PrintDefaults() | 264 fs.PrintDefaults() |
267 | 265 |
268 i, err := python.Find(c, python.Version{}, lp.look) | 266 i, err := python.Find(c, python.Version{}, lp.look) |
269 if err != nil { | 267 if err != nil { |
270 » » return errors.Annotate(err).Reason("could not find Python interp
reter for help").Err() | 268 » » return errors.Annotate(err, "could not find Python interpreter f
or help").Err() |
271 } | 269 } |
272 | 270 |
273 // Redirect all "--help" to Stdout for consistency. | 271 // Redirect all "--help" to Stdout for consistency. |
274 fmt.Fprintf(os.Stdout, "\nPython help for %s:\n", i.Python) | 272 fmt.Fprintf(os.Stdout, "\nPython help for %s:\n", i.Python) |
275 cmd := i.IsolatedCommand(c, "--help") | 273 cmd := i.IsolatedCommand(c, "--help") |
276 cmd.Stdout = os.Stdout | 274 cmd.Stdout = os.Stdout |
277 cmd.Stderr = os.Stdout | 275 cmd.Stderr = os.Stdout |
278 if err := cmd.Run(); err != nil { | 276 if err := cmd.Run(); err != nil { |
279 » » return errors.Annotate(err).Reason("failed to dump Python help f
rom: %(interpreter)s"). | 277 » » return errors.Annotate(err, "failed to dump Python help from: %s
", i.Python).Err() |
280 » » » D("interpreter", i.Python). | |
281 » » » Err() | |
282 } | 278 } |
283 return nil | 279 return nil |
284 } | 280 } |
285 | 281 |
286 // Main is the main application entry point. | 282 // Main is the main application entry point. |
287 func (cfg *Config) Main(c context.Context) int { | 283 func (cfg *Config) Main(c context.Context) int { |
288 // Implementation of "checkWrapper": if CheckWrapperENV is set, we immed
iately | 284 // Implementation of "checkWrapper": if CheckWrapperENV is set, we immed
iately |
289 // exit with a non-zero value. | 285 // exit with a non-zero value. |
290 env := environ.System() | 286 env := environ.System() |
291 if wrapperCheck(env) { | 287 if wrapperCheck(env) { |
(...skipping 20 matching lines...) Expand all Loading... |
312 }, | 308 }, |
313 logConfig: logging.Config{ | 309 logConfig: logging.Config{ |
314 Level: logging.Error, | 310 Level: logging.Error, |
315 }, | 311 }, |
316 } | 312 } |
317 | 313 |
318 return run(c, func(c context.Context) error { | 314 return run(c, func(c context.Context) error { |
319 return a.mainImpl(c, os.Args[0], os.Args[1:]) | 315 return a.mainImpl(c, os.Args[0], os.Args[1:]) |
320 }) | 316 }) |
321 } | 317 } |
OLD | NEW |