// compromised, an error is returned.
func BImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
// catch panics and return them as errors
+ const currentVersion = 6
+ version := -1 // unknown version
defer func() {
if e := recover(); e != nil {
- // The package (filename) causing the problem is added to this
- // error by a wrapper in the caller (Import in gcimporter.go).
// Return a (possibly nil or incomplete) package unchanged (see #16088).
- err = fmt.Errorf("cannot import, possibly version skew (%v) - reinstall package", e)
+ if version > currentVersion {
+ err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e)
+ } else {
+ err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e)
+ }
}
}()
- if len(data) > 0 && data[0] == 'i' {
- return iImportData(fset, imports, data[1:], path)
- }
-
p := importer{
imports: imports,
data: data,
importpath: path,
- version: -1, // unknown version
+ version: version,
strList: []string{""}, // empty string is mapped to 0
pathList: []string{""}, // empty string is mapped to 0
fake: fakeFileSet{
p.posInfoFormat = p.int() != 0
versionstr = p.string()
if versionstr == "v1" {
- p.version = 0
+ version = 0
}
} else {
// Go1.8 extensible encoding
versionstr = p.rawStringln(b)
if s := strings.SplitN(versionstr, " ", 3); len(s) >= 2 && s[0] == "version" {
if v, err := strconv.Atoi(s[1]); err == nil && v > 0 {
- p.version = v
+ version = v
}
}
}
+ p.version = version
// read version specific flags - extend as necessary
switch p.version {
- // case 7:
+ // case currentVersion:
// ...
// fallthrough
- case 6, 5, 4, 3, 2, 1:
+ case currentVersion, 5, 4, 3, 2, 1:
p.debugFormat = p.rawStringln(p.rawByte()) == "debug"
p.trackAllTypes = p.int() != 0
p.posInfoFormat = p.int() != 0
case 0:
// Go1.7 encoding format - nothing to do here
default:
- errorf("unknown export format version %d (%q)", p.version, versionstr)
+ errorf("unknown bexport format version %d (%q)", p.version, versionstr)
}
// --- generic export data ---
switch hdr {
case "$$\n":
err = fmt.Errorf("import %q: old export format no longer supported (recompile library)", path)
+
case "$$B\n":
var data []byte
data, err = ioutil.ReadAll(buf)
- if err == nil {
- // TODO(gri): allow clients of go/importer to provide a FileSet.
- // Or, define a new standard go/types/gcexportdata package.
- fset := token.NewFileSet()
+ if err != nil {
+ break
+ }
+
+ // TODO(gri): allow clients of go/importer to provide a FileSet.
+ // Or, define a new standard go/types/gcexportdata package.
+ fset := token.NewFileSet()
+
+ // The indexed export format starts with an 'i'; the older
+ // binary export format starts with a 'c', 'd', or 'v'
+ // (from "version"). Select appropriate importer.
+ if len(data) > 0 && data[0] == 'i' {
+ _, pkg, err = iImportData(fset, packages, data[1:], id)
+ } else {
_, pkg, err = BImportData(fset, packages, data, id)
- return
}
+
default:
err = fmt.Errorf("unknown export data header: %q", hdr)
}
}
pkgpath := "./" + name[:len(name)-2]
+ if testing.Verbose() {
+ t.Logf("importing %s", name)
+ }
+
// test that export data can be imported
_, err := Import(make(map[string]*types.Package), pkgpath, dir, nil)
if err != nil {
+ // ok to fail if it fails with a newer version error for select files
+ if strings.Contains(err.Error(), "newer version") {
+ switch name {
+ case "test_go1.11_999b.a", "test_go1.11_999i.a":
+ continue
+ }
+ // fall through
+ }
t.Errorf("import %q failed: %v", pkgpath, err)
continue
}
import (
"bytes"
"encoding/binary"
+ "fmt"
"go/constant"
"go/token"
"go/types"
// If the export data version is not recognized or the format is otherwise
// compromised, an error is returned.
func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
+ const currentVersion = 0
+ version := -1
+ defer func() {
+ if e := recover(); e != nil {
+ if version > currentVersion {
+ err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e)
+ } else {
+ err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e)
+ }
+ }
+ }()
+
r := &intReader{bytes.NewReader(data), path}
- version := r.uint64()
+ version = int(r.uint64())
switch version {
- case 0:
+ case currentVersion:
default:
- errorf("cannot import %q: unknown iexport format version %d", path, version)
+ errorf("unknown iexport format version %d", version)
}
sLen := int64(r.uint64())
//
// go build -o test_go1.$X_$Y.a test.go
//
-// with $X = Go version and $Y = export format version.
+// with $X = Go version and $Y = export format version
+// (add 'b' or 'i' to distinguish between binary and
+// indexed format starting with 1.11 as long as both
+// formats are supported).
//
// Make sure this source is extended such that it exercises
// whatever export format change has taken place.