Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(309)

Side by Side Diff: vpython/application/application.go

Issue 2705593003: vpython: Add application entry point. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | vpython/application/subcommand_install.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 application
6
7 import (
8 "flag"
9 "io/ioutil"
10 "os"
11 "path/filepath"
12 "time"
13
14 "github.com/luci/luci-go/vpython"
15 "github.com/luci/luci-go/vpython/api/env"
16 "github.com/luci/luci-go/vpython/filesystem"
17 "github.com/luci/luci-go/vpython/python"
18 "github.com/luci/luci-go/vpython/spec"
19 "github.com/luci/luci-go/vpython/venv"
20
21 "github.com/luci/luci-go/common/cli"
22 "github.com/luci/luci-go/common/errors"
23 "github.com/luci/luci-go/common/logging"
24 "github.com/luci/luci-go/common/logging/gologger"
25 "github.com/luci/luci-go/common/system/environ"
26
27 "github.com/maruel/subcommands"
28 "github.com/mitchellh/go-homedir"
29 "golang.org/x/net/context"
30 )
31
32 // An A is an application's default configuration.
iannucci 2017/02/23 02:24:22 why not Config (e.g. application.Config) or Defaul
dnj 2017/03/11 18:07:40 Made "Config".
33 type A struct {
34 // PackageLoader is the package loader to use.
iannucci 2017/02/23 02:24:22 no documented default values?
dnj 2017/03/11 18:07:40 Nope, no default values at all! The counterpart o
35 PackageLoader venv.PackageLoader
36
37 // VENVPackage is the VirtualEnv package to use for bootstrap generation .
38 VENVPackage env.Spec_Package
39
40 // PruneThreshold, if > 0, is the maximum age of a VirtualEnv before it
41 // becomes candidate for pruning. If <= 0, no pruning will be performed.
42 //
43 // See venv.Config's PruneThreshold.
44 PruneThreshold time.Duration
45 // PruneLimit, if > 0, is the maximum number of VirtualEnv that should b e
46 // pruned passively. If <= 0, no limit will be applied.
47 //
48 // See venv.Config's PruneLimit.
49 PruneLimit int
iannucci 2017/02/23 02:24:22 same comments as venv.Config about defaults and na
dnj 2017/03/11 18:07:40 Done.
50
51 // Opts is the set of configured options.
52 Opts vpython.Options
53 }
54
55 func (a *A) mainDev(c context.Context) error {
56 app := cli.Application{
57 Name: "vpython",
58 Title: "VirtualEnv Python Bootstrap (Development Mode)",
59 Context: func(context.Context) context.Context {
60 // Discard the entry Context and use the one passed to u s.
iannucci 2017/02/23 02:24:22 why? testing? maybe docstring this func? edit: o
dnj 2017/03/11 18:07:40 OR... giving subcommands actual Context awareness
61 c := c
62
63 // Install our A instance into the Context.
64 c = withApplication(c, a)
65
66 // Drop down to Info level debugging.
67 if logging.GetLevel(c) > logging.Info {
68 c = logging.SetLevel(c, logging.Info)
69 }
70 return c
71 },
72 Commands: []*subcommands.Command{
73 subcommands.CmdHelp,
74 subcommandInstall,
75 },
76 }
77
78 return python.Error(subcommands.Run(&app, a.Opts.Args))
79 }
80
81 func (a *A) mainImpl(c context.Context, args []string) error {
82 logConfig := logging.Config{
83 Level: logging.Warning,
84 }
85
86 hdir, err := homedir.Dir()
87 if err != nil {
88 return errors.Annotate(err).Reason("failed to get user home dire ctory").Err()
89 }
90
91 a.Opts = vpython.Options{
92 EnvConfig: venv.Config{
93 BaseDir: filepath.Join(hdir, ".vpython"),
94 MaxHashLen: 6,
95 Package: a.VENVPackage,
96 PruneThreshold: a.PruneThreshold,
97 PruneLimit: a.PruneLimit,
98 Loader: a.PackageLoader,
99 },
100 WaitForEnv: true,
101 Environ: environ.System(),
102 }
103 var specPath string
104 var devMode bool
105
106 fs := flag.NewFlagSet("", flag.ExitOnError)
107 fs.BoolVar(&devMode, "dev", devMode,
108 "Enter development / subcommand mode (use 'help' for more option s).")
109 fs.StringVar(&a.Opts.EnvConfig.Python, "python", a.Opts.EnvConfig.Python ,
110 "Path to system Python interpreter to use. Default is found on P ATH.")
111 fs.StringVar(&a.Opts.WorkDir, "workdir", a.Opts.WorkDir,
112 "Working directory to run the Python interpreter in. Default is current working directory.")
113 fs.StringVar(&a.Opts.EnvConfig.BaseDir, "root", a.Opts.EnvConfig.BaseDir ,
114 "Path to virtual enviornment root directory. Default is the work ing directory. "+
115 "If explicitly set to empty string, a temporary director y will be used and cleaned up "+
116 "on completion.")
117 fs.StringVar(&specPath, "spec", specPath,
118 "Path to enviornment specification file to load. Default probes for one.")
119 logConfig.AddFlags(fs)
120
121 if err := fs.Parse(args); err != nil {
122 if err == flag.ErrHelp {
123 return nil
124 }
125 return errors.Annotate(err).Reason("failed to parse flags").Err( )
126 }
127 a.Opts.Args = fs.Args()
128
129 c = logConfig.Set(c)
130
131 // If an spec path was manually specified, load and use it.
132 if specPath != "" {
133 var err error
134 if a.Opts.EnvConfig.Spec, err = spec.Load(specPath); err != nil {
135 return errors.Annotate(err).Reason("failed to load envir onment specification file (-env) from: %(path)s").
136 D("path", specPath).
137 Err()
138 }
139 }
140
141 // If an empty BaseDir was specified, use a temporary directory and clea n it
142 // up on completion.
143 if a.Opts.EnvConfig.BaseDir == "" {
144 tdir, err := ioutil.TempDir("", "vpython")
145 if err != nil {
146 return errors.Annotate(err).Reason("failed to create tem porary directory").Err()
147 }
148 defer func() {
149 logging.Debugf(c, "Removing temporary directory: %s", td ir)
150 if terr := filesystem.RemoveAll(tdir); terr != nil {
151 logging.WithError(terr).Warningf(c, "Failed to c lean up temporary directory; leaking: %s", tdir)
152 }
153 }()
154 a.Opts.EnvConfig.BaseDir = tdir
155 }
156
157 // Development mode (subcommands).
158 if devMode {
159 return a.mainDev(c)
160 }
161
162 if err := vpython.Run(c, a.Opts); err != nil {
163 return errors.Annotate(err).Err()
164 }
165 return nil
166 }
167
168 // Main is the main application entry point.
169 func (a *A) Main(c context.Context) int {
170 c = gologger.StdConfig.Use(c)
171 c = logging.SetLevel(c, logging.Warning)
172
173 return run(c, func(c context.Context) error {
174 return a.mainImpl(c, os.Args[1:])
175 })
176 }
OLDNEW
« no previous file with comments | « no previous file | vpython/application/subcommand_install.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698