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

Side by Side Diff: vpython/venv/config.go

Issue 2963503003: [errors] Greatly simplify common/errors package. (Closed)
Patch Set: fix nits Created 3 years, 5 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 | « vpython/spec/spec.go ('k') | vpython/venv/iterator.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 venv 5 package venv
6 6
7 import ( 7 import (
8 "fmt" 8 "fmt"
9 "os" 9 "os"
10 "path/filepath" 10 "path/filepath"
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 return nil, errors.New("no package loader provided") 133 return nil, errors.New("no package loader provided")
134 } 134 }
135 135
136 // Resolve our base directory, if one is not supplied. 136 // Resolve our base directory, if one is not supplied.
137 if cfg.BaseDir == "" { 137 if cfg.BaseDir == "" {
138 // Use one in a temporary directory. 138 // Use one in a temporary directory.
139 cfg.BaseDir = filepath.Join(os.TempDir(), "vpython") 139 cfg.BaseDir = filepath.Join(os.TempDir(), "vpython")
140 logging.Debugf(c, "Using tempdir-relative environment root: %s", cfg.BaseDir) 140 logging.Debugf(c, "Using tempdir-relative environment root: %s", cfg.BaseDir)
141 } 141 }
142 if err := filesystem.AbsPath(&cfg.BaseDir); err != nil { 142 if err := filesystem.AbsPath(&cfg.BaseDir); err != nil {
143 » » return nil, errors.Annotate(err).Reason("failed to resolve absol ute path of base directory").Err() 143 » » return nil, errors.Annotate(err, "failed to resolve absolute pat h of base directory").Err()
144 } 144 }
145 145
146 // Enforce maximum path length. 146 // Enforce maximum path length.
147 if cfg.MaxScriptPathLen > 0 { 147 if cfg.MaxScriptPathLen > 0 {
148 if longestPath := longestGeneratedScriptPath(cfg.BaseDir); longe stPath != "" { 148 if longestPath := longestGeneratedScriptPath(cfg.BaseDir); longe stPath != "" {
149 longestPathLen := utf8.RuneCountInString(longestPath) 149 longestPathLen := utf8.RuneCountInString(longestPath)
150 if longestPathLen > cfg.MaxScriptPathLen { 150 if longestPathLen > cfg.MaxScriptPathLen {
151 » » » » return nil, errors.Reason("expected deepest path length (%(len)d) exceeds threshold (%(threshold)d)"). 151 » » » » return nil, errors.Reason(
152 » » » » » D("len", longestPathLen). 152 » » » » » "expected deepest path length (%d) excee ds threshold (%d)",
153 » » » » » D("threshold", cfg.MaxScriptPathLen). 153 » » » » » longestPathLen, cfg.MaxScriptPathLen,
154 » » » » » D("longestPath", longestPath). 154 » » » » ).InternalReason("longestPath(%q)", longestPath) .Err()
155 » » » » » Err()
156 } 155 }
157 } 156 }
158 } 157 }
159 158
160 // Construct a new, independent Environment for this Env. 159 // Construct a new, independent Environment for this Env.
161 e = e.Clone() 160 e = e.Clone()
162 if cfg.Spec != nil { 161 if cfg.Spec != nil {
163 e.Spec = cfg.Spec.Clone() 162 e.Spec = cfg.Spec.Clone()
164 } 163 }
165 if err := spec.NormalizeEnvironment(e); err != nil { 164 if err := spec.NormalizeEnvironment(e); err != nil {
166 » » return nil, errors.Annotate(err).Reason("invalid environment").E rr() 165 » » return nil, errors.Annotate(err, "invalid environment").Err()
167 } 166 }
168 167
169 // If the environment doesn't specify a VirtualEnv package (expected), u se 168 // If the environment doesn't specify a VirtualEnv package (expected), u se
170 // our default. 169 // our default.
171 if e.Spec.Virtualenv == nil { 170 if e.Spec.Virtualenv == nil {
172 e.Spec.Virtualenv = &cfg.Package 171 e.Spec.Virtualenv = &cfg.Package
173 } 172 }
174 173
175 if err := cfg.Loader.Resolve(c, e); err != nil { 174 if err := cfg.Loader.Resolve(c, e); err != nil {
176 » » return nil, errors.Annotate(err).Reason("failed to resolve packa ges").Err() 175 » » return nil, errors.Annotate(err, "failed to resolve packages").E rr()
177 } 176 }
178 177
179 if err := cfg.resolvePythonInterpreter(c, e.Spec); err != nil { 178 if err := cfg.resolvePythonInterpreter(c, e.Spec); err != nil {
180 » » return nil, errors.Annotate(err).Reason("failed to resolve syste m Python interpreter").Err() 179 » » return nil, errors.Annotate(err, "failed to resolve system Pytho n interpreter").Err()
181 } 180 }
182 e.Runtime.Path = cfg.si.Python 181 e.Runtime.Path = cfg.si.Python
183 e.Runtime.Version = e.Spec.PythonVersion 182 e.Runtime.Version = e.Spec.PythonVersion
184 183
185 var err error 184 var err error
186 if e.Runtime.Hash, err = cfg.si.Hash(); err != nil { 185 if e.Runtime.Hash, err = cfg.si.Hash(); err != nil {
187 return nil, err 186 return nil, err
188 } 187 }
189 logging.Debugf(c, "Resolved system Python runtime (%s @ %s): %s", 188 logging.Debugf(c, "Resolved system Python runtime (%s @ %s): %s",
190 e.Runtime.Version, e.Runtime.Hash, e.Runtime.Path) 189 e.Runtime.Version, e.Runtime.Hash, e.Runtime.Path)
191 190
192 // Ensure that our base directory exists. 191 // Ensure that our base directory exists.
193 if err := filesystem.MakeDirs(cfg.BaseDir); err != nil { 192 if err := filesystem.MakeDirs(cfg.BaseDir); err != nil {
194 » » return nil, errors.Annotate(err).Reason("could not create enviro nment root: %(root)s"). 193 » » return nil, errors.Annotate(err, "could not create environment r oot: %s", cfg.BaseDir).Err()
195 » » » D("root", cfg.BaseDir).
196 » » » Err()
197 } 194 }
198 195
199 // Generate our environment name based on the deterministic hash of its 196 // Generate our environment name based on the deterministic hash of its
200 // fully-resolved specification. 197 // fully-resolved specification.
201 envName := cfg.OverrideName 198 envName := cfg.OverrideName
202 if envName == "" { 199 if envName == "" {
203 envName = cfg.envNameForSpec(e.Spec, e.Runtime) 200 envName = cfg.envNameForSpec(e.Spec, e.Runtime)
204 } 201 }
205 env := cfg.envForName(envName, e) 202 env := cfg.envForName(envName, e)
206 return env, nil 203 return env, nil
207 } 204 }
208 205
209 // EnvName returns the VirtualEnv environment name for the environment that cfg 206 // EnvName returns the VirtualEnv environment name for the environment that cfg
210 // describes. 207 // describes.
211 func (cfg *Config) envNameForSpec(s *vpython.Spec, rt *vpython.Runtime) string { 208 func (cfg *Config) envNameForSpec(s *vpython.Spec, rt *vpython.Runtime) string {
212 name := spec.Hash(s, rt, EnvironmentVersion) 209 name := spec.Hash(s, rt, EnvironmentVersion)
213 if cfg.MaxHashLen > 0 && len(name) > cfg.MaxHashLen { 210 if cfg.MaxHashLen > 0 && len(name) > cfg.MaxHashLen {
214 name = name[:cfg.MaxHashLen] 211 name = name[:cfg.MaxHashLen]
215 } 212 }
216 return name 213 return name
217 } 214 }
218 215
219 // Prune performs a pruning round on the environment set described by this 216 // Prune performs a pruning round on the environment set described by this
220 // Config. 217 // Config.
221 func (cfg *Config) Prune(c context.Context) error { 218 func (cfg *Config) Prune(c context.Context) error {
222 if err := prune(c, cfg, nil); err != nil { 219 if err := prune(c, cfg, nil); err != nil {
223 » » return errors.Annotate(err).Err() 220 » » return errors.Annotate(err, "").Err()
224 } 221 }
225 return nil 222 return nil
226 } 223 }
227 224
228 // envForName creates an Env for a named directory. 225 // envForName creates an Env for a named directory.
229 // 226 //
230 // The Environment, e, can be nil; however, code paths that require it may not 227 // The Environment, e, can be nil; however, code paths that require it may not
231 // be called. 228 // be called.
232 func (cfg *Config) envForName(name string, e *vpython.Environment) *Env { 229 func (cfg *Config) envForName(name string, e *vpython.Environment) *Env {
233 // Env-specific root directory: <BaseDir>/<name> 230 // Env-specific root directory: <BaseDir>/<name>
234 venvRoot := filepath.Join(cfg.BaseDir, name) 231 venvRoot := filepath.Join(cfg.BaseDir, name)
235 binDir := venvBinDir(venvRoot) 232 binDir := venvBinDir(venvRoot)
236 return &Env{ 233 return &Env{
237 Config: cfg, 234 Config: cfg,
238 Root: venvRoot, 235 Root: venvRoot,
239 Name: name, 236 Name: name,
240 Python: filepath.Join(binDir, "python"), 237 Python: filepath.Join(binDir, "python"),
241 Environment: e, 238 Environment: e,
242 BinDir: binDir, 239 BinDir: binDir,
243 EnvironmentStampPath: filepath.Join(venvRoot, fmt.Sprintf("envir onment.%s.pb.txt", vpython.Version)), 240 EnvironmentStampPath: filepath.Join(venvRoot, fmt.Sprintf("envir onment.%s.pb.txt", vpython.Version)),
244 241
245 lockPath: filepath.Join(cfg.BaseDir, fmt.Sprintf(".%s.lo ck", name)), 242 lockPath: filepath.Join(cfg.BaseDir, fmt.Sprintf(".%s.lo ck", name)),
246 completeFlagPath: filepath.Join(venvRoot, "complete.flag"), 243 completeFlagPath: filepath.Join(venvRoot, "complete.flag"),
247 } 244 }
248 } 245 }
249 246
250 func (cfg *Config) resolvePythonInterpreter(c context.Context, s *vpython.Spec) error { 247 func (cfg *Config) resolvePythonInterpreter(c context.Context, s *vpython.Spec) error {
251 specVers, err := python.ParseVersion(s.PythonVersion) 248 specVers, err := python.ParseVersion(s.PythonVersion)
252 if err != nil { 249 if err != nil {
253 » » return errors.Annotate(err).Reason("failed to parse Python versi on from: %(value)q"). 250 » » return errors.Annotate(err, "failed to parse Python version from : %q", s.PythonVersion).Err()
254 » » » D("value", s.PythonVersion).
255 » » » Err()
256 } 251 }
257 252
258 if cfg.Python == "" { 253 if cfg.Python == "" {
259 // No explicitly-specified Python path. Determine one based on t he 254 // No explicitly-specified Python path. Determine one based on t he
260 // specification. 255 // specification.
261 if cfg.si, err = python.Find(c, specVers, cfg.LookPathFunc); err != nil { 256 if cfg.si, err = python.Find(c, specVers, cfg.LookPathFunc); err != nil {
262 » » » return errors.Annotate(err).Reason("could not find Pytho n for: %(vers)s"). 257 » » » return errors.Annotate(err, "could not find Python for: %s", specVers).Err()
263 » » » » D("vers", specVers).
264 » » » » Err()
265 } 258 }
266 cfg.Python = cfg.si.Python 259 cfg.Python = cfg.si.Python
267 } else { 260 } else {
268 cfg.si = &python.Interpreter{ 261 cfg.si = &python.Interpreter{
269 Python: cfg.Python, 262 Python: cfg.Python,
270 } 263 }
271 } 264 }
272 if err := cfg.si.Normalize(); err != nil { 265 if err := cfg.si.Normalize(); err != nil {
273 return err 266 return err
274 } 267 }
275 268
276 // Confirm that the version of the interpreter matches that which is 269 // Confirm that the version of the interpreter matches that which is
277 // expected. 270 // expected.
278 interpreterVers, err := cfg.si.GetVersion(c) 271 interpreterVers, err := cfg.si.GetVersion(c)
279 if err != nil { 272 if err != nil {
280 » » return errors.Annotate(err).Reason("failed to determine Python v ersion for: %(python)s"). 273 » » return errors.Annotate(err, "failed to determine Python version for: %s", cfg.Python).Err()
281 » » » D("python", cfg.Python).
282 » » » Err()
283 } 274 }
284 if !specVers.IsSatisfiedBy(interpreterVers) { 275 if !specVers.IsSatisfiedBy(interpreterVers) {
285 » » return errors.Reason("supplied Python version (%(supplied)s) doe sn't match specification (%(spec)s)"). 276 » » return errors.Reason("supplied Python version (%s) doesn't match specification (%s)", interpreterVers, specVers).Err()
286 » » » D("supplied", interpreterVers).
287 » » » D("spec", specVers).
288 » » » Err()
289 } 277 }
290 s.PythonVersion = interpreterVers.String() 278 s.PythonVersion = interpreterVers.String()
291 279
292 // Resolve to absolute path. 280 // Resolve to absolute path.
293 if err := filesystem.AbsPath(&cfg.Python); err != nil { 281 if err := filesystem.AbsPath(&cfg.Python); err != nil {
294 » » return errors.Annotate(err).Reason("could not get absolute path for: %(python)s"). 282 » » return errors.Annotate(err, "could not get absolute path for: %s ", cfg.Python).Err()
295 » » » D("python", cfg.Python).
296 » » » Err()
297 } 283 }
298 return nil 284 return nil
299 } 285 }
300 286
301 func (cfg *Config) systemInterpreter() *python.Interpreter { return cfg.si } 287 func (cfg *Config) systemInterpreter() *python.Interpreter { return cfg.si }
OLDNEW
« no previous file with comments | « vpython/spec/spec.go ('k') | vpython/venv/iterator.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698