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

Unified Diff: vpython/python/interpreter.go

Issue 2905943002: [vpython] Incorporate interpreter path/hash. (Closed)
Patch Set: Created 3 years, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « vpython/python/find.go ('k') | vpython/python/python_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: vpython/python/interpreter.go
diff --git a/vpython/python/interpreter.go b/vpython/python/interpreter.go
index 2a1fcf3820a5e4dcd3705a2d9e31187ef04b040d..f3326cf36c4a33d0fac7046f4396b995999712f9 100644
--- a/vpython/python/interpreter.go
+++ b/vpython/python/interpreter.go
@@ -5,11 +5,17 @@
package python
import (
+ "crypto/sha256"
+ "encoding/hex"
+ "io"
+ "os"
"os/exec"
+ "path/filepath"
"strings"
"sync"
"github.com/luci/luci-go/common/errors"
+ "github.com/luci/luci-go/common/system/filesystem"
"golang.org/x/net/context"
)
@@ -27,11 +33,33 @@ type Interpreter struct {
cachedVersion *Version
cachedVersionMu sync.Mutex
+ // cachedHash is the cached SHA256 hash string of the interpreter's binary
+ // contents. It is populated once, protected by cachedHashOnce.
+ cachedHash string
+ cachedHashErr error
+ cachedHashOnce sync.Once
+
// testCommandHook, if not nil, is called on generated Command results prior
// to returning them.
testCommandHook func(*exec.Cmd)
}
+// Normalize normalizes the Interpreter configuration by resolving relative
+// paths into absolute paths and evaluating symlnks.
+func (i *Interpreter) Normalize() error {
+ if err := filesystem.AbsPath(&i.Python); err != nil {
+ return err
+ }
+ resolved, err := filepath.EvalSymlinks(i.Python)
+ if err != nil {
+ return errors.Annotate(err).Reason("could not evaluate symlinks for: %(path)q").
+ D("path", i.Python).
+ Err()
+ }
+ i.Python = resolved
+ return nil
+}
+
// IsolatedCommand returns a configurable exec.Cmd structure bound to this
// Interpreter.
//
@@ -85,6 +113,34 @@ func (i *Interpreter) GetVersion(c context.Context) (v Version, err error) {
return
}
+// Hash returns the SHA256 hash string of this interpreter.
+//
+// The hash value is cached; if called multiple times, the cached value will
+// be returned.
+func (i *Interpreter) Hash() (string, error) {
+ hashInterpreter := func(path string) (string, error) {
+ fd, err := os.Open(i.Python)
+ if err != nil {
+ return "", errors.Annotate(err).Reason("failed to open interpreter").Err()
+ }
+ defer fd.Close()
+
+ hash := sha256.New()
+ if _, err := io.Copy(hash, fd); err != nil {
+ return "", errors.Annotate(err).Reason("failed to read [%(path)s] for hashing").
+ D("path", path).
+ Err()
+ }
+
+ return hex.EncodeToString(hash.Sum(nil)), nil
+ }
+
+ i.cachedHashOnce.Do(func() {
+ i.cachedHash, i.cachedHashErr = hashInterpreter(i.Python)
+ })
+ return i.cachedHash, i.cachedHashErr
+}
+
func parseVersionOutput(output string) (Version, error) {
// Expected output:
// Python X.Y.Z
« no previous file with comments | « vpython/python/find.go ('k') | vpython/python/python_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698