6
6
package build
7
7
8
8
import (
9
+ "bytes"
10
+ "crypto/sha256"
9
11
"fmt"
10
12
"go/ast"
11
13
"go/build"
12
14
"go/parser"
13
15
"go/scanner"
14
16
"go/token"
15
17
"go/types"
18
+ "io"
16
19
"io/ioutil"
17
20
"os"
18
21
"os/exec"
19
22
"path"
20
23
"path/filepath"
21
24
"strconv"
22
25
"strings"
23
- "time"
24
26
25
27
"github.com/fsnotify/fsnotify"
26
28
"github.com/gopherjs/gopherjs/compiler"
@@ -409,11 +411,10 @@ func (o *Options) PrintSuccess(format string, a ...interface{}) {
409
411
// GopherJS requires.
410
412
type PackageData struct {
411
413
* build.Package
412
- JSFiles []string
413
- IsTest bool // IsTest is true if the package is being built for running tests.
414
- SrcModTime time.Time
415
- UpToDate bool
416
- IsVirtual bool // If true, the package does not have a corresponding physical directory on disk.
414
+ JSFiles []string
415
+ IsTest bool // IsTest is true if the package is being built for running tests.
416
+ UpToDate bool
417
+ IsVirtual bool // If true, the package does not have a corresponding physical directory on disk.
417
418
418
419
bctx * build.Context // The original build context this package came from.
419
420
}
@@ -593,19 +594,19 @@ func (s *Session) BuildPackage(pkg *PackageData) (*compiler.Archive, error) {
593
594
return archive , nil
594
595
}
595
596
597
+ pkgHash := sha256 .New ()
598
+
596
599
if pkg .PkgObj != "" {
597
- var fileInfo os.FileInfo
598
- gopherjsBinary , err := os .Executable ()
599
- if err == nil {
600
- fileInfo , err = os .Stat (gopherjsBinary )
601
- if err == nil {
602
- pkg .SrcModTime = fileInfo .ModTime ()
603
- }
600
+ binPath , err := os .Executable ()
601
+ if err != nil {
602
+ return nil , fmt .Errorf ("could not locate GopherJS binary: %v" , err )
604
603
}
604
+ binFile , err := os .Open (binPath )
605
605
if err != nil {
606
- os .Stderr .WriteString ("Could not get GopherJS binary's modification timestamp. Please report issue.\n " )
607
- pkg .SrcModTime = time .Now ()
606
+ return nil , fmt .Errorf ("could not open %v: %v" , binPath , err )
608
607
}
608
+ defer binFile .Close ()
609
+ io .Copy (pkgHash , binFile )
609
610
610
611
for _ , importedPkgPath := range pkg .Imports {
611
612
// Ignore all imports that aren't mentioned in import specs of pkg.
@@ -627,50 +628,57 @@ func (s *Session) BuildPackage(pkg *PackageData) (*compiler.Archive, error) {
627
628
if importedPkgPath == "unsafe" || ignored {
628
629
continue
629
630
}
630
- importedPkg , _ , err := s .buildImportPathWithSrcDir (importedPkgPath , pkg .Dir )
631
+ _ , importedArchive , err := s .buildImportPathWithSrcDir (importedPkgPath , pkg .Dir )
631
632
if err != nil {
632
633
return nil , err
633
634
}
634
- impModTime := importedPkg .SrcModTime
635
- if impModTime .After (pkg .SrcModTime ) {
636
- pkg .SrcModTime = impModTime
637
- }
635
+
636
+ fmt .Fprintf (pkgHash , "import: %v\n " , importedPkgPath )
637
+ fmt .Fprintf (pkgHash , " hash: %v\n " , importedArchive .Hash )
638
638
}
639
639
640
640
for _ , name := range append (pkg .GoFiles , pkg .JSFiles ... ) {
641
- fileInfo , err := statFile (filepath .Join (pkg .Dir , name ))
641
+ fp := filepath .Join (pkg .Dir , name )
642
+ file , err := s .bctx .OpenFile (fp )
642
643
if err != nil {
643
- return nil , err
644
- }
645
- if fileInfo .ModTime ().After (pkg .SrcModTime ) {
646
- pkg .SrcModTime = fileInfo .ModTime ()
644
+ return nil , fmt .Errorf ("failed to open %v: %v" , fp , err )
647
645
}
646
+ fmt .Fprintf (pkgHash , "file: %v\n " , fp )
647
+ n , _ := io .Copy (pkgHash , file )
648
+ fmt .Fprintf (pkgHash , "%d bytes\n " , n )
648
649
}
649
650
650
- pkgObjFileInfo , err := os .Stat (pkg .PkgObj )
651
- if err == nil && ! pkg .SrcModTime .After (pkgObjFileInfo .ModTime ()) {
652
- // package object is up to date, load from disk if library
653
- pkg .UpToDate = true
654
- if pkg .IsCommand () {
655
- return nil , nil
656
- }
651
+ // no commands are archived
652
+ if pkg .IsCommand () {
653
+ goto CacheMiss
654
+ }
657
655
658
- objFile , err := os .Open (pkg .PkgObj )
659
- if err != nil {
660
- return nil , err
656
+ objFile , err := os .Open (pkg .PkgObj )
657
+ if err != nil {
658
+ if os .IsNotExist (err ) {
659
+ goto CacheMiss
661
660
}
662
- defer objFile .Close ()
661
+ return nil , err
662
+ }
663
+ defer objFile .Close ()
663
664
664
- archive , err := compiler .ReadArchive (pkg .PkgObj , pkg .ImportPath , objFile , s .Types )
665
- if err != nil {
666
- return nil , err
667
- }
665
+ archive , err := compiler .ReadArchive (pkg .PkgObj , pkg .ImportPath , objFile , s .Types )
666
+ if err != nil {
667
+ return nil , err
668
+ }
668
669
670
+ if bytes .Equal (archive .Hash , pkgHash .Sum (nil )) {
669
671
s .Archives [pkg .ImportPath ] = archive
670
- return archive , err
672
+ return archive , nil
671
673
}
672
674
}
673
675
676
+ CacheMiss:
677
+
678
+ if s .options .Verbose {
679
+ fmt .Printf ("Cache miss for %v\n " , pkg .ImportPath )
680
+ }
681
+
674
682
fileSet := token .NewFileSet ()
675
683
files , err := parseAndAugment (s .xctx , pkg , pkg .IsTest , fileSet )
676
684
if err != nil {
@@ -697,6 +705,8 @@ func (s *Session) BuildPackage(pkg *PackageData) (*compiler.Archive, error) {
697
705
return nil , err
698
706
}
699
707
708
+ archive .Hash = pkgHash .Sum (nil )
709
+
700
710
for _ , jsFile := range pkg .JSFiles {
701
711
code , err := ioutil .ReadFile (filepath .Join (pkg .Dir , jsFile ))
702
712
if err != nil {
@@ -707,10 +717,6 @@ func (s *Session) BuildPackage(pkg *PackageData) (*compiler.Archive, error) {
707
717
archive .IncJSCode = append (archive .IncJSCode , []byte ("\n \t }).call($global);\n " )... )
708
718
}
709
719
710
- if s .options .Verbose {
711
- fmt .Println (pkg .ImportPath )
712
- }
713
-
714
720
s .Archives [pkg .ImportPath ] = archive
715
721
716
722
if pkg .PkgObj == "" || pkg .IsCommand () {
0 commit comments