dep.go | 24 ++++++++++++------------ depfix.go | 8 ++++---- inode.go | 39 ++++++++++++++++++++------------------- main.go | 8 +++++--- ood.go | 3 ++- run.go | 4 ++-- diff --git a/dep.go b/dep.go index a9d9855b8ed72c8ec02ee4080568f5e094e9d9d2a479adfd99294cb7251b4672..a301a0e0c4032a06b5578718ca086601f4680b6e4d55a814655861a67570bb98 100644 --- a/dep.go +++ b/dep.go @@ -67,11 +67,12 @@ } type Ifchange struct { tgt *Tgt - meta string + meta [InodeLen + HashLen]byte } -func (ifchange *Ifchange) Inode() Inode { - return Inode(ifchange.meta[:InodeLen]) +func (ifchange *Ifchange) Inode() *Inode { + inode := Inode(ifchange.meta[:InodeLen]) + return &inode } func (ifchange *Ifchange) Hash() Hash { @@ -140,7 +141,7 @@ } } _, err = io.Copy(w, bytes.NewBuffer(chunkWrite(bytes.Join([][]byte{ {DepTypeIfchange}, - []byte(inode), + inode[:], []byte(hsh), []byte(tgt.RelTo(cwd)), }, nil)))) @@ -226,20 +227,19 @@ func depBinIfchangeParse(tgt *Tgt, chunk []byte) (*Ifchange, string, error) { if len(chunk) < InodeLen+HashLen+1 { return nil, "", errors.New("too short \"ifchange\" format") } - name := string(chunk[InodeLen+HashLen:]) - meta := string(chunk[:InodeLen+HashLen]) tgtH, _ := pathSplit(tgt.a) - ifchange := &Ifchange{tgt: NewTgt(path.Join(tgtH, name)), meta: meta} - cachedFound := false + name := string(chunk[InodeLen+HashLen:]) + ifchange := &Ifchange{ + tgt: NewTgt(path.Join(tgtH, name)), + meta: ([InodeLen + HashLen]byte)(chunk), + } for _, cached := range IfchangeCache[ifchange.tgt.rel] { if ifchange.meta == cached.meta { - ifchange = cached - cachedFound = true - break + return cached, name, nil } } - if IfchangeCache != nil && !cachedFound { + if IfchangeCache != nil { IfchangeCache[ifchange.tgt.rel] = append(IfchangeCache[ifchange.tgt.rel], ifchange) } return ifchange, name, nil diff --git a/depfix.go b/depfix.go index 8a27eacbd5ca0e3e250635eccc15a0cf57d2110cbc4c82f6f1011ad552090b85..59bd7db1786f8a3b6d6f81af626b2ff02c8dd145ce7ceecef4d16f020d127363 100644 --- a/depfix.go +++ b/depfix.go @@ -156,7 +156,7 @@ fd, err = os.Open(p) if err != nil { break } - var inode Inode + var inode *Inode inode, _, err = inodeFromFileByFd(fd) if err != nil { fd.Close() @@ -174,7 +174,7 @@ fd.Close() _, err = io.Copy(fdDepW, bytes.NewBuffer( chunkWrite(bytes.Join([][]byte{ {DepTypeIfchange}, - []byte(inode), + inode[:], []byte(hsh), []byte(name), }, nil)))) @@ -244,7 +244,7 @@ fd, err = os.Open(p) if err != nil { break } - var inode Inode + var inode *Inode inode, _, err = inodeFromFileByFd(fd) if err != nil { fd.Close() @@ -262,7 +262,7 @@ fd.Close() _, err = io.Copy(fdDepW, bytes.NewBuffer( chunkWrite(bytes.Join([][]byte{ {DepTypeIfchange}, - []byte(inode), + inode[:], []byte(hsh), []byte(name), }, nil)))) diff --git a/inode.go b/inode.go index 6ec715449773081879bfa49565ceb80aa96a1e31eeff884eea3f3fa2dc0c58ca..b5ad6c3f56114037adcc7460d364ab178ef67828dd5244faf45e01d9c831ddc2 100644 --- a/inode.go +++ b/inode.go @@ -20,6 +20,7 @@ package main import ( + "bytes" "encoding/binary" "os" "strconv" @@ -45,26 +46,26 @@ var InodeTrust InodeTrustType // It is big-endian 64-bit unsigned integers: size, inodeNum, // ctime sec, ctime nsec, mtime sec, mtime nsec. -type Inode string +type Inode [InodeLen]byte -func (our Inode) Equals(their Inode) bool { - if our[:2*8] != their[:2*8] { +func (our *Inode) Equals(their *Inode) bool { + if !bytes.Equal(our[:2*8], their[:2*8]) { return false } switch InodeTrust { case InodeTrustCtime: - if our[2*8:4*8] != their[2*8:4*8] { + if !bytes.Equal(our[2*8:4*8], their[2*8:4*8]) { return false } case InodeTrustMtime: - if our[4*8:6*8] != their[4*8:6*8] { + if !bytes.Equal(our[4*8:6*8], their[4*8:6*8]) { return false } } return true } -func (inode Inode) RecfileFields() []recfile.Field { +func (inode *Inode) RecfileFields() []recfile.Field { return []recfile.Field{ {Name: "Size", Value: strconv.FormatUint(binary.BigEndian.Uint64( []byte(inode[0*8:1*8])), 10)}, @@ -81,21 +82,21 @@ []byte(inode[5*8:6*8])), 10)}, } } -func inodeFromFileStat(fi os.FileInfo, stat unix.Stat_t) Inode { +func inodeFromFileStat(fi os.FileInfo, stat unix.Stat_t) *Inode { ctimeSec, ctimeNsec := stat.Ctim.Unix() mtimeSec := fi.ModTime().Unix() mtimeNsec := fi.ModTime().UnixNano() - buf := make([]byte, InodeLen) - binary.BigEndian.PutUint64(buf[0*8:1*8], uint64(fi.Size())) - binary.BigEndian.PutUint64(buf[1*8:2*8], uint64(stat.Ino)) - binary.BigEndian.PutUint64(buf[2*8:3*8], uint64(ctimeSec)) - binary.BigEndian.PutUint64(buf[3*8:4*8], uint64(ctimeNsec)) - binary.BigEndian.PutUint64(buf[4*8:5*8], uint64(mtimeSec)) - binary.BigEndian.PutUint64(buf[5*8:6*8], uint64(mtimeNsec)) - return Inode(buf) + inode := new(Inode) + binary.BigEndian.PutUint64(inode[0*8:1*8], uint64(fi.Size())) + binary.BigEndian.PutUint64(inode[1*8:2*8], uint64(stat.Ino)) + binary.BigEndian.PutUint64(inode[2*8:3*8], uint64(ctimeSec)) + binary.BigEndian.PutUint64(inode[3*8:4*8], uint64(ctimeNsec)) + binary.BigEndian.PutUint64(inode[4*8:5*8], uint64(mtimeSec)) + binary.BigEndian.PutUint64(inode[5*8:6*8], uint64(mtimeNsec)) + return inode } -func inodeFromFileByFd(fd *os.File) (inode Inode, isDir bool, err error) { +func inodeFromFileByFd(fd *os.File) (inode *Inode, isDir bool, err error) { fi, err := fd.Stat() if err != nil { return @@ -113,15 +114,15 @@ inode = inodeFromFileStat(fi, stat) return } -func inodeFromFileByPath(p string) (Inode, error) { +func inodeFromFileByPath(p string) (*Inode, error) { fi, err := os.Stat(p) if err != nil { - return "", err + return nil, err } var stat unix.Stat_t err = unix.Stat(p, &stat) if err != nil { - return "", err + return nil, err } return inodeFromFileStat(fi, stat), nil } diff --git a/main.go b/main.go index 1df0ae28f4fcbafe045a86fcb9cde5c24cfcf082d7b445cda6aff4f6e9f46099..1111a7f37523411c960406e7208806b6208bcaff9ab5dad0ba1ca211deb19857 100644 --- a/main.go +++ b/main.go @@ -507,7 +507,7 @@ IfchangeCache = nil DepFixHashCache = make(map[string]Hash) err = depFix(Cwd) case CmdNameRedoInode: - var inode Inode + var inode *Inode for _, tgt := range tgts { inode, err = inodeFromFileByPath(tgt.a) if err != nil { @@ -542,6 +542,7 @@ break } var typ byte var chunk []byte + var inode Inode for len(data) > 0 { typ, chunk, data, _ = chunkRead(data) switch typ { @@ -561,7 +562,7 @@ {Name: "Target", Value: string(chunk)}, }...) case DepTypeIfchange: name := string(chunk[InodeLen+HashLen:]) - meta := string(chunk[:InodeLen+HashLen]) + meta := chunk[:InodeLen+HashLen] fields := []recfile.Field{ {Name: "Type", Value: "ifchange"}, {Name: "Target", Value: name}, @@ -569,7 +570,8 @@ } fields = append(fields, recfile.Field{ Name: "Hash", Value: Hash(meta[InodeLen:]).String(), }) - fields = append(fields, Inode(meta[:InodeLen]).RecfileFields()...) + inode = Inode(meta[:][:InodeLen]) + fields = append(fields, inode.RecfileFields()...) err = recfileWrite(w, fields...) case DepTypeIfchangeNonex: err = recfileWrite(w, []recfile.Field{ diff --git a/ood.go b/ood.go index efb86bc80c41cd46d3602d4522346f13c8156b34fb031edc35b58a1715d862e3..6da0c4430ed0604fb25ee87380c6bfccc825aa80a11f84ffc438950bcafd1227 100644 --- a/ood.go +++ b/ood.go @@ -20,6 +20,7 @@ package main import ( + "bytes" "errors" "fmt" "io" @@ -161,7 +162,7 @@ } return ood, TgtError{tgt, ErrLine(err)} } - if inode[:8] != ifchange.Inode()[:8] { + if !bytes.Equal(inode[:8], ifchange.Inode()[:8]) { tracef(CDebug, "ood: %s%s -> %s: size differs", indent, tgt, ifchange.tgt) ood = true OODCache[ifchange.tgt.rel] = ood diff --git a/run.go b/run.go index 345e16681130c724323476cd94dfc9fbe7650f4d2ae9afdda4c001239bde274a..1d5303e8fe929d5cffc67bc963b65bce4135dd95416a225d3dc4d227015c9485 100644 --- a/run.go +++ b/run.go @@ -133,7 +133,7 @@ return os.MkdirAll(pth, os.FileMode(0777)) } func isModified(dep *Dep, tgt *Tgt) ( - modified bool, ourInode Inode, hshPrev Hash, err error, + modified bool, ourInode *Inode, hshPrev Hash, err error, ) { if dep == nil { return @@ -666,7 +666,7 @@ } // Was $1 touched? if inode, err := inodeFromFileByPath(tgt.a); err == nil { - if inodePrev == "" { + if inodePrev == nil { runErr.Err = Err1WasTouched errs <- runErr return