1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
package watch
import (
"fmt"
"io/ioutil"
"os"
"regexp"
"time"
)
var goRegExp = regexp.MustCompile(`\.go$`)
var goTestRegExp = regexp.MustCompile(`_test\.go$`)
type PackageHash struct {
CodeModifiedTime time.Time
TestModifiedTime time.Time
Deleted bool
path string
codeHash string
testHash string
}
func NewPackageHash(path string) *PackageHash {
p := &PackageHash{
path: path,
}
p.codeHash, _, p.testHash, _, p.Deleted = p.computeHashes()
return p
}
func (p *PackageHash) CheckForChanges() bool {
codeHash, codeModifiedTime, testHash, testModifiedTime, deleted := p.computeHashes()
if deleted {
if p.Deleted == false {
t := time.Now()
p.CodeModifiedTime = t
p.TestModifiedTime = t
}
p.Deleted = true
return true
}
modified := false
p.Deleted = false
if p.codeHash != codeHash {
p.CodeModifiedTime = codeModifiedTime
modified = true
}
if p.testHash != testHash {
p.TestModifiedTime = testModifiedTime
modified = true
}
p.codeHash = codeHash
p.testHash = testHash
return modified
}
func (p *PackageHash) computeHashes() (codeHash string, codeModifiedTime time.Time, testHash string, testModifiedTime time.Time, deleted bool) {
infos, err := ioutil.ReadDir(p.path)
if err != nil {
deleted = true
return
}
for _, info := range infos {
if info.IsDir() {
continue
}
if goTestRegExp.Match([]byte(info.Name())) {
testHash += p.hashForFileInfo(info)
if info.ModTime().After(testModifiedTime) {
testModifiedTime = info.ModTime()
}
continue
}
if goRegExp.Match([]byte(info.Name())) {
codeHash += p.hashForFileInfo(info)
if info.ModTime().After(codeModifiedTime) {
codeModifiedTime = info.ModTime()
}
}
}
testHash += codeHash
if codeModifiedTime.After(testModifiedTime) {
testModifiedTime = codeModifiedTime
}
return
}
func (p *PackageHash) hashForFileInfo(info os.FileInfo) string {
return fmt.Sprintf("%s_%d_%d", info.Name(), info.Size(), info.ModTime().UnixNano())
}
|