]> Cypherpunks.ru repositories - goredo.git/blobdiff - ood.go
Do not use deprecated os.SEEK_*
[goredo.git] / ood.go
diff --git a/ood.go b/ood.go
index e75dd43c4f7185dd17b7047d326414a6af9b89cd..717f2ac9fc7097a11c20f901ce583580caa0f8b8 100644 (file)
--- 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 <stargrave@stargrave.org>
 
 This program is free software: you can redistribute it and/or modify
@@ -22,10 +22,13 @@ package main
 import (
        "errors"
        "fmt"
+       "io"
        "os"
        "path"
        "path/filepath"
        "strings"
+
+       "golang.org/x/sys/unix"
 )
 
 const (
@@ -33,6 +36,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 +122,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 +151,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 +182,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 +198,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, io.SeekEnd); 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)
+}