Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Next Next commit
compiler: use hash calculation for determining staleness
  • Loading branch information
myitcv committed May 4, 2018
commit e807fdbace0e13dcac5813adb331ffe3f9b1d1b0
95 changes: 50 additions & 45 deletions build/build.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package build

import (
"bytes"
"crypto/sha256"
"fmt"
"go/ast"
"go/build"
Expand All @@ -17,7 +19,6 @@ import (
"runtime"
"strconv"
"strings"
"time"

"github.com/fsnotify/fsnotify"
"github.com/gopherjs/gopherjs/compiler"
Expand Down Expand Up @@ -457,11 +458,10 @@ func (o *Options) PrintSuccess(format string, a ...interface{}) {

type PackageData struct {
*build.Package
JSFiles []string
IsTest bool // IsTest is true if the package is being built for running tests.
SrcModTime time.Time
UpToDate bool
IsVirtual bool // If true, the package does not have a corresponding physical directory on disk.
JSFiles []string
IsTest bool // IsTest is true if the package is being built for running tests.
UpToDate bool
IsVirtual bool // If true, the package does not have a corresponding physical directory on disk.
}

type Session struct {
Expand Down Expand Up @@ -596,19 +596,19 @@ func (s *Session) BuildPackage(pkg *PackageData) (*compiler.Archive, error) {
return archive, nil
}

pkgHash := sha256.New()

if pkg.PkgObj != "" {
var fileInfo os.FileInfo
gopherjsBinary, err := os.Executable()
if err == nil {
fileInfo, err = os.Stat(gopherjsBinary)
if err == nil {
pkg.SrcModTime = fileInfo.ModTime()
}
binPath, err := os.Executable()
if err != nil {
return nil, fmt.Errorf("could not locate GopherJS binary: %v", err)
}
binFile, err := os.Open(binPath)
if err != nil {
os.Stderr.WriteString("Could not get GopherJS binary's modification timestamp. Please report issue.\n")
pkg.SrcModTime = time.Now()
return nil, fmt.Errorf("could not open %v: %v", binPath, err)
}
defer binFile.Close()
io.Copy(pkgHash, binFile)

for _, importedPkgPath := range pkg.Imports {
// Ignore all imports that aren't mentioned in import specs of pkg.
Expand All @@ -630,50 +630,57 @@ func (s *Session) BuildPackage(pkg *PackageData) (*compiler.Archive, error) {
if importedPkgPath == "unsafe" || ignored {
continue
}
importedPkg, _, err := s.buildImportPathWithSrcDir(importedPkgPath, pkg.Dir)
_, importedArchive, err := s.buildImportPathWithSrcDir(importedPkgPath, pkg.Dir)
if err != nil {
return nil, err
}
impModTime := importedPkg.SrcModTime
if impModTime.After(pkg.SrcModTime) {
pkg.SrcModTime = impModTime
}

fmt.Fprintf(pkgHash, "import: %v\n", importedPkgPath)
fmt.Fprintf(pkgHash, " hash: %v\n", importedArchive.Hash)
}

for _, name := range append(pkg.GoFiles, pkg.JSFiles...) {
fileInfo, err := statFile(filepath.Join(pkg.Dir, name))
fp := filepath.Join(pkg.Dir, name)
file, err := s.bctx.OpenFile(fp)
if err != nil {
return nil, err
}
if fileInfo.ModTime().After(pkg.SrcModTime) {
pkg.SrcModTime = fileInfo.ModTime()
return nil, fmt.Errorf("failed to open %v: %v", fp, err)
}
fmt.Fprintf(pkgHash, "file: %v\n", fp)
n, _ := io.Copy(pkgHash, file)
fmt.Fprintf(pkgHash, "%d bytes\n", n)
}

pkgObjFileInfo, err := os.Stat(pkg.PkgObj)
if err == nil && !pkg.SrcModTime.After(pkgObjFileInfo.ModTime()) {
// package object is up to date, load from disk if library
pkg.UpToDate = true
if pkg.IsCommand() {
return nil, nil
}
// no commands are archived
if pkg.IsCommand() {
goto CacheMiss
}

objFile, err := os.Open(pkg.PkgObj)
if err != nil {
return nil, err
objFile, err := os.Open(pkg.PkgObj)
if err != nil {
if os.IsNotExist(err) {
goto CacheMiss
}
defer objFile.Close()
return nil, err
}
defer objFile.Close()

archive, err := compiler.ReadArchive(pkg.PkgObj, pkg.ImportPath, objFile, s.Types)
if err != nil {
return nil, err
}
archive, err := compiler.ReadArchive(pkg.PkgObj, pkg.ImportPath, objFile, s.Types)
if err != nil {
return nil, err
}

if bytes.Equal(archive.Hash, pkgHash.Sum(nil)) {
s.Archives[pkg.ImportPath] = archive
return archive, err
return archive, nil
}
}

CacheMiss:

if s.options.Verbose {
fmt.Printf("Cache miss for %v\n", pkg.ImportPath)
}

fileSet := token.NewFileSet()
files, err := parseAndAugment(s.bctx, pkg.Package, pkg.IsTest, fileSet)
if err != nil {
Expand All @@ -700,6 +707,8 @@ func (s *Session) BuildPackage(pkg *PackageData) (*compiler.Archive, error) {
return nil, err
}

archive.Hash = pkgHash.Sum(nil)

for _, jsFile := range pkg.JSFiles {
code, err := ioutil.ReadFile(filepath.Join(pkg.Dir, jsFile))
if err != nil {
Expand All @@ -710,10 +719,6 @@ func (s *Session) BuildPackage(pkg *PackageData) (*compiler.Archive, error) {
archive.IncJSCode = append(archive.IncJSCode, []byte("\n\t}).call($global);\n")...)
}

if s.options.Verbose {
fmt.Println(pkg.ImportPath)
}

s.Archives[pkg.ImportPath] = archive

if pkg.PkgObj == "" || pkg.IsCommand() {
Expand Down
1 change: 1 addition & 0 deletions compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func (err ErrorList) Error() string {
}

type Archive struct {
Hash []byte
ImportPath string
Name string
Imports []string
Expand Down