X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=ood.go;h=cad1ce38f5f23f6beb1124749774a7d4111303ec;hb=ce96a1c785b32af13264225c0bf7ae8370a5af21;hp=e75dd43c4f7185dd17b7047d326414a6af9b89cd;hpb=ebd96d2c56c742d9d00bccb9faee5fc1a7db664a;p=goredo.git diff --git a/ood.go b/ood.go index e75dd43..cad1ce3 100644 --- a/ood.go +++ b/ood.go @@ -1,5 +1,5 @@ /* -goredo -- redo implementation on pure Go +goredo -- djb's redo implementation on pure Go Copyright (C) 2020-2021 Sergey Matveev This program is free software: you can redistribute it and/or modify @@ -26,6 +26,8 @@ import ( "path" "path/filepath" "strings" + + "golang.org/x/sys/unix" ) const ( @@ -33,6 +35,15 @@ const ( DepTypeIfchange = "ifchange" DepTypeAlways = "always" DepTypeStamp = "stamp" + + EnvOODTgtsFd = "REDO_OOD_TGTS_FD" + EnvOODTgtsLockFd = "REDO_OOD_TGTS_LOCK_FD" +) + +var ( + OODTgts map[string]struct{} + FdOODTgts *os.File + FdOODTgtsLock *os.File ) type TgtErr struct { @@ -110,11 +121,11 @@ func isOOD(cwd, tgtOrig string, level int, seen map[string]struct{}) (bool, erro for _, m := range depInfo.ifchanges { dep := m["Target"] if dep == "" { - return ood, TgtErr{tgtOrig, errors.New("invalid format of .dep: missing Target")} + return ood, TgtErr{tgtOrig, errors.New("invalid format of .rec: missing Target")} } theirInode, err := inodeFromRec(m) if err != nil { - return ood, TgtErr{tgtOrig, fmt.Errorf("invalid format of .dep: %v", err)} + return ood, TgtErr{tgtOrig, fmt.Errorf("invalid format of .rec: %v", err)} } theirHsh := m["Hash"] trace(CDebug, "ood: %s%s -> %s: checking", indent, tgtOrig, dep) @@ -139,7 +150,7 @@ func isOOD(cwd, tgtOrig string, level int, seen map[string]struct{}) (bool, erro ood = true goto Done } - if inode.Equals(theirInode) { + if InodeTrust && inode.Equals(theirInode) { trace(CDebug, "ood: %s%s -> %s: same inode", indent, tgtOrig, dep) } else { trace(CDebug, "ood: %s%s -> %s: inode differs", indent, tgtOrig, dep) @@ -170,7 +181,7 @@ func isOOD(cwd, tgtOrig string, level int, seen map[string]struct{}) (bool, erro continue } - depOod, err := isOOD(cwd, dep, level+1, seen) + depOod, err := isOODWithTrace(cwd, dep, level+1, seen) if err != nil { return ood, TgtErr{tgtOrig, err} } @@ -186,3 +197,49 @@ Done: trace(CDebug, "ood: %s%s: %v", indent, tgtOrig, ood) return ood, nil } + +func isOODWithTrace( + cwd, tgtOrig string, + level int, + seen map[string]struct{}, +) (bool, error) { + p, err := filepath.Abs(path.Join(cwd, tgtOrig)) + if err != nil { + panic(err) + } + _, ood := OODTgts[p] + if ood { + trace( + CDebug, + "ood: %s%s true, external decision", + strings.Repeat(". ", level), tgtOrig, + ) + goto RecordOODTgt + } + ood, err = isOOD(cwd, tgtOrig, level, seen) + if !ood { + return ood, err + } +RecordOODTgt: + if err = unix.Flock(int(FdOODTgtsLock.Fd()), unix.LOCK_EX); err != nil { + panic(err) + } + if _, err = FdOODTgts.Seek(0, os.SEEK_END); err != nil { + panic(err) + } + if _, err := FdOODTgts.WriteString(p + "\x00"); err != nil { + panic(err) + } + unix.Flock(int(FdOODTgtsLock.Fd()), unix.LOCK_UN) + return true, nil +} + +func oodTgtsClear() { + if err := unix.Flock(int(FdOODTgtsLock.Fd()), unix.LOCK_EX); err != nil { + panic(err) + } + if err := FdOODTgts.Truncate(0); err != nil { + panic(err) + } + unix.Flock(int(FdOODTgtsLock.Fd()), unix.LOCK_UN) +}