X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=ood.go;h=120a7de8afd554d95cb8397c01182a4db6eac99e;hb=refs%2Fheads%2Fmaster;hp=9a70be41a54bbc95776a632f90453804154a27cb;hpb=0db0e21921706ba645c229e809fd3668542dcaae;p=goredo.git diff --git a/ood.go b/ood.go index 9a70be4..120a7de 100644 --- a/ood.go +++ b/ood.go @@ -1,25 +1,24 @@ -/* -goredo -- djb's redo implementation on pure Go -Copyright (C) 2020-2023 Sergey Matveev - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, version 3 of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ +// goredo -- djb's redo implementation on pure Go +// Copyright (C) 2020-2024 Sergey Matveev +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 3 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . // Out-of-date determination package main import ( + "bytes" "errors" "fmt" "io" @@ -32,11 +31,6 @@ import ( ) const ( - DepTypeIfcreate = "ifcreate" - DepTypeIfchange = "ifchange" - DepTypeAlways = "always" - DepTypeStamp = "stamp" - EnvOODTgtsFd = "REDO_OOD_TGTS_FD" EnvOODTgtsLockFd = "REDO_OOD_TGTS_LOCK_FD" ) @@ -48,9 +42,6 @@ var ( OODCache = make(map[string]bool) FileExistsCache = make(map[string]bool) - DepInfoCache = make(map[string]*DepInfo) - - ErrMissingTarget = errors.New("invalid format of .rec: missing Target") ) func FileExists(p string) bool { @@ -86,29 +77,29 @@ func isSrc(tgt *Tgt) bool { if FileExists(tgt.a + ".do") { return false } - if FileExists(tgt.Dep()) { + if FileExists(tgt.dep) { return false } return true } func isOODByBuildUUID(tgt *Tgt) bool { - build, err := depReadBuild(tgt.Dep()) + build, err := depBuildRead(tgt.dep) return err != nil || build != BuildUUID } func isOOD(tgt *Tgt, level int, seen map[string]*Tgt) (bool, error) { indent := strings.Repeat(". ", level) tracef(CDebug, "ood: %s%s checking", indent, tgt) - ood, cached := OODCache[tgt.a] + ood, cached := OODCache[tgt.rel] if cached { tracef(CDebug, "ood: %s%s -> cached: %v", indent, tgt, ood) return ood, nil } - depInfo := DepInfoCache[tgt.Dep()] + dep := DepCache[tgt.rel] var err error - if depInfo == nil { - depInfo, err = depRead(tgt) + if dep == nil { + dep, err = depRead(tgt) if err != nil { if errors.Is(err, fs.ErrNotExist) { if isSrc(tgt) { @@ -116,70 +107,70 @@ func isOOD(tgt *Tgt, level int, seen map[string]*Tgt) (bool, error) { tracef(CDebug, "ood: %s%s -> is source", indent, tgt) } else { ood = true - tracef(CDebug, "ood: %s%s -> no dep: %s", indent, tgt, tgt.Dep()) + tracef(CDebug, "ood: %s%s -> no dep: %s", indent, tgt, tgt.dep) } - OODCache[tgt.a] = ood + OODCache[tgt.rel] = ood return ood, nil } if err != nil { return true, TgtError{tgt, ErrLine(err)} } } - DepInfoCache[tgt.Dep()] = depInfo + DepCache[tgt.rel] = dep } - if depInfo.build == BuildUUID { + if dep.build == BuildUUID { tracef(CDebug, "ood: %s%s -> already built", indent, tgt) - OODCache[tgt.a] = false + OODCache[tgt.rel] = false return false, nil } if !FileExists(tgt.a) { tracef(CDebug, "ood: %s%s -> non-existent", indent, tgt) - OODCache[tgt.a] = true + OODCache[tgt.rel] = true return true, nil } - for _, dep := range depInfo.ifcreates { - if FileExists(dep.a) { - tracef(CDebug, "ood: %s%s -> %s created", indent, tgt, dep) + for _, ifcreate := range dep.ifcreates { + if FileExists(ifcreate.a) { + tracef(CDebug, "ood: %s%s -> %s created", indent, tgt, ifcreate) ood = true goto Done } } - for _, dep := range depInfo.ifchanges { - tracef(CDebug, "ood: %s%s -> %s: checking", indent, tgt, dep.tgt) - ood, cached = OODCache[dep.tgt.a] + for _, ifchange := range dep.ifchanges { + tracef(CDebug, "ood: %s%s -> %s: checking", indent, tgt, ifchange.tgt) + ood, cached = OODCache[ifchange.tgt.rel] if cached { - tracef(CDebug, "ood: %s%s -> %s: cached: %v", indent, tgt, dep.tgt, ood) + tracef(CDebug, "ood: %s%s -> %s: cached: %v", indent, tgt, ifchange.tgt, ood) if ood { goto Done } continue } - inode, err := inodeFromFileByPath(dep.tgt.a) + inode, err := inodeFromFileByPath(ifchange.tgt.a) if err != nil { if errors.Is(err, fs.ErrNotExist) { - tracef(CDebug, "ood: %s%s -> %s: not exists", indent, tgt, dep.tgt) + tracef(CDebug, "ood: %s%s -> %s: not exists", indent, tgt, ifchange.tgt) ood = true - OODCache[dep.tgt.a] = ood + OODCache[ifchange.tgt.rel] = ood goto Done } return ood, TgtError{tgt, ErrLine(err)} } - if inode.Size != dep.inode.Size { - tracef(CDebug, "ood: %s%s -> %s: size differs", indent, tgt, dep.tgt) + if !bytes.Equal(inode[:8], ifchange.Inode()[:8]) { + tracef(CDebug, "ood: %s%s -> %s: size differs", indent, tgt, ifchange.tgt) ood = true - OODCache[dep.tgt.a] = ood + OODCache[ifchange.tgt.rel] = ood goto Done } - if InodeTrust != InodeTrustNone && inode.Equals(dep.inode) { - tracef(CDebug, "ood: %s%s -> %s: same inode", indent, tgt, dep.tgt) + if InodeTrust != InodeTrustNone && inode.Equals(ifchange.Inode()) { + tracef(CDebug, "ood: %s%s -> %s: same inode", indent, tgt, ifchange.tgt) } else { - tracef(CDebug, "ood: %s%s -> %s: inode differs", indent, tgt, dep.tgt) - fd, err := os.Open(dep.tgt.a) + tracef(CDebug, "ood: %s%s -> %s: inode differs", indent, tgt, ifchange.tgt) + fd, err := os.Open(ifchange.tgt.a) if err != nil { return ood, TgtError{tgt, ErrLine(err)} } @@ -188,46 +179,46 @@ func isOOD(tgt *Tgt, level int, seen map[string]*Tgt) (bool, error) { if err != nil { return ood, TgtError{tgt, ErrLine(err)} } - if dep.hash != hsh { - tracef(CDebug, "ood: %s%s -> %s: hash differs", indent, tgt, dep.tgt) + if ifchange.Hash() != hsh { + tracef(CDebug, "ood: %s%s -> %s: hash differs", indent, tgt, ifchange.tgt) ood = true - OODCache[dep.tgt.a] = ood + OODCache[ifchange.tgt.rel] = ood goto Done } - tracef(CDebug, "ood: %s%s -> %s: same hash", indent, tgt, dep.tgt) + tracef(CDebug, "ood: %s%s -> %s: same hash", indent, tgt, ifchange.tgt) } - if dep.tgt.a == tgt.a { - tracef(CDebug, "ood: %s%s -> %s: same target", indent, tgt, dep.tgt) + if ifchange.tgt.rel == tgt.rel { + tracef(CDebug, "ood: %s%s -> %s: same target", indent, tgt, ifchange.tgt) continue } - if isSrc(dep.tgt) { - tracef(CDebug, "ood: %s%s -> %s: is source", indent, tgt, dep.tgt) - OODCache[dep.tgt.a] = false + if isSrc(ifchange.tgt) { + tracef(CDebug, "ood: %s%s -> %s: is source", indent, tgt, ifchange.tgt) + OODCache[ifchange.tgt.rel] = false continue } - if _, ok := seen[dep.tgt.a]; ok { - tracef(CDebug, "ood: %s%s -> %s: was always built", indent, tgt, dep.tgt) - OODCache[dep.tgt.a] = false + if _, ok := seen[ifchange.tgt.rel]; ok { + tracef(CDebug, "ood: %s%s -> %s: was always built", indent, tgt, ifchange.tgt) + OODCache[ifchange.tgt.rel] = false continue } - depOOD, err := isOODWithTrace(dep.tgt, level+1, seen) + depOOD, err := isOODWithTrace(ifchange.tgt, level+1, seen) if err != nil { return ood, TgtError{tgt, err} } if depOOD { - tracef(CDebug, "ood: %s%s -> %s: ood", indent, tgt, dep.tgt) + tracef(CDebug, "ood: %s%s -> %s: ood", indent, tgt, ifchange.tgt) ood = true goto Done } - tracef(CDebug, "ood: %s%s -> %s: !ood", indent, tgt, dep.tgt) + tracef(CDebug, "ood: %s%s -> %s: !ood", indent, tgt, ifchange.tgt) } Done: tracef(CDebug, "ood: %s%s: %v", indent, tgt, ood) - OODCache[tgt.a] = ood + OODCache[tgt.rel] = ood return ood, nil }