]> Cypherpunks.ru repositories - goredo.git/blobdiff - main.go
Repetitive OOD optimization
[goredo.git] / main.go
diff --git a/main.go b/main.go
index 2e0778b0831c5a913a39e2c2e371f377c5010cca..4de78be52fa786830cfbb92862c1c495cd59140a 100644 (file)
--- a/main.go
+++ b/main.go
@@ -1,6 +1,6 @@
 /*
-goredo -- redo implementation on pure Go
-Copyright (C) 2020 Sergey Matveev <stargrave@stargrave.org>
+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
 it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@ package main
 
 import (
        "bufio"
+       "bytes"
        "crypto/rand"
        "flag"
        "fmt"
@@ -60,7 +61,7 @@ func mustParseFd(v, name string) *os.File {
 func main() {
        version := flag.Bool("version", false, "print version")
        warranty := flag.Bool("warranty", false, "print warranty information")
-       symlinks := flag.Bool("symlinks", false, "create necessary symlinks in current direcotyr")
+       symlinks := flag.Bool("symlinks", false, "create necessary symlinks in current directory")
 
        flag.Usage = usage
        flag.Parse()
@@ -91,27 +92,30 @@ func main() {
                                log.Println(err)
                        }
                }
-               fmt.Println("not creating optional:", os.Args[0], "<- tai64nlocal")
                os.Exit(rc)
        }
        log.SetFlags(0)
 
        var err error
-       Cwd, err = unix.Getwd()
+       Cwd, err = os.Getwd()
        if err != nil {
-               panic(err)
+               log.Fatalln(err)
        }
 
        NoColor = os.Getenv(EnvNoColor) != ""
        NoSync = os.Getenv(EnvNoSync) == "1"
+       InodeTrust = os.Getenv(EnvInodeNoTrust) == ""
 
        TopDir = os.Getenv(EnvTopDir)
-       if TopDir != "" {
+       if TopDir == "" {
+               TopDir = "/"
+       } else {
                TopDir, err = filepath.Abs(TopDir)
                if err != nil {
                        panic(err)
                }
        }
+       DirPrefix = os.Getenv(EnvDirPrefix)
 
        if *flagStderrKeep {
                mustSetenv(EnvStderrKeep, "1")
@@ -119,6 +123,9 @@ func main() {
        if *flagStderrSilent {
                mustSetenv(EnvStderrSilent, "1")
        }
+       if *flagNoProgress {
+               mustSetenv(EnvNoProgress, "1")
+       }
        if *flagDebug {
                mustSetenv(EnvDebug, "1")
        }
@@ -136,6 +143,7 @@ func main() {
        }
        StderrKeep = os.Getenv(EnvStderrKeep) == "1"
        StderrSilent = os.Getenv(EnvStderrSilent) == "1"
+       NoProgress = os.Getenv(EnvNoProgress) == "1"
        Debug = os.Getenv(EnvDebug) == "1"
        LogWait = os.Getenv(EnvLogWait) == "1"
        LogLock = os.Getenv(EnvLogLock) == "1"
@@ -144,6 +152,9 @@ func main() {
                MyPid = os.Getpid()
        }
        var traced bool
+       if *flagTraceAll {
+               mustSetenv(EnvTrace, "1")
+       }
        if *flagTrace {
                traced = true
        } else {
@@ -151,6 +162,46 @@ func main() {
        }
 
        // Those are internal envs
+       FdOODTgts, err = ioutil.TempFile("", "ood-tgts")
+       if err != nil {
+               panic(err)
+       }
+       if err = os.Remove(FdOODTgts.Name()); err != nil {
+               panic(err)
+       }
+       FdOODTgtsLock, err = ioutil.TempFile("", "ood-tgts.lock")
+       if err != nil {
+               panic(err)
+       }
+       if err = os.Remove(FdOODTgtsLock.Name()); err != nil {
+               panic(err)
+       }
+
+       if v := os.Getenv(EnvOODTgtsFd); v != "" {
+               fd := mustParseFd(v, EnvOODTgtsFd)
+               fdLock := mustParseFd(v, EnvOODTgtsLockFd)
+               if err = unix.Flock(int(fdLock.Fd()), unix.LOCK_EX); err != nil {
+                       panic(err)
+               }
+               if _, err = fd.Seek(0, os.SEEK_SET); err != nil {
+                       panic(err)
+               }
+               tgtsRaw, err := ioutil.ReadAll(bufio.NewReader(fd))
+               if err != nil {
+                       panic(err)
+               }
+               unix.Flock(int(fdLock.Fd()), unix.LOCK_UN)
+               OODTgts = make(map[string]struct{})
+               for _, tgtRaw := range bytes.Split(tgtsRaw, []byte{0}) {
+                       t := string(tgtRaw)
+                       if t == "" {
+                               continue
+                       }
+                       OODTgts[t] = struct{}{}
+                       trace(CDebug, "ood: known to be: %s", t)
+               }
+       }
+
        StderrPrefix = os.Getenv(EnvStderrPrefix)
        if v := os.Getenv(EnvLevel); v != "" {
                Level, err = strconv.Atoi(v)
@@ -161,32 +212,44 @@ func main() {
                        panic("negative " + EnvLevel)
                }
        }
+
        var fdDep *os.File
        if v := os.Getenv(EnvDepFd); v != "" {
                fdDep = mustParseFd(v, EnvDepFd)
        }
+
+       tgts := flag.Args()
        BuildUUID = os.Getenv(EnvBuildUUID)
        if BuildUUID == "" {
                raw := new([16]byte)
                if _, err = io.ReadFull(rand.Reader, raw[:]); err != nil {
-                       panic(err)
+                       log.Fatalln(err)
                }
                raw[6] = (raw[6] & 0x0F) | uint8(4<<4) // version 4
                BuildUUID = fmt.Sprintf(
                        "%x-%x-%x-%x-%x",
                        raw[0:4], raw[4:6], raw[6:8], raw[8:10], raw[10:],
                )
+               if len(tgts) == 0 {
+                       tgts = []string{"all"}
+               }
        }
+
        statusInit()
 
-       tgts := flag.Args()
-       if len(tgts) == 0 {
-               tgts = []string{"all"}
+       for i, tgt := range tgts {
+               if path.IsAbs(tgt) {
+                       tgts[i] = cwdMustRel(tgt)
+               }
        }
+
        ok := true
        err = nil
        cmdName := path.Base(os.Args[0])
-       trace(CDebug, "[%s] run: %s %s [%s]", BuildUUID, cmdName, tgts, Cwd)
+       trace(
+               CDebug, "[%s] run: %s %s cwd:%s dirprefix:%s",
+               BuildUUID, cmdName, tgts, Cwd, DirPrefix,
+       )
 
 CmdSwitch:
        switch cmdName {
@@ -199,7 +262,9 @@ CmdSwitch:
                }
        case "redo-ifchange":
                ok, err = ifchange(tgts, false, traced)
-               writeDeps(fdDep, tgts)
+               if err == nil {
+                       err = writeDeps(fdDep, tgts)
+               }
        case "redo-ifcreate":
                if fdDep == nil {
                        log.Fatalln("no", EnvDepFd)
@@ -245,18 +310,19 @@ CmdSwitch:
                        log.Fatalln("single target expected")
                }
                var fdTmp *os.File
-               fdTmp, err = ioutil.TempFile("", "")
+               fdTmp, err = ioutil.TempFile("", "whichdo")
                if err != nil {
                        break
                }
-               os.Remove(fdTmp.Name())
-               var doFile string
+               if err = os.Remove(fdTmp.Name()); err != nil {
+                       break
+               }
                cwd, tgt := cwdAndTgt(tgts[0])
-               doFile, _, err = findDo(fdTmp, cwd, tgt)
+               doFile, upLevels, err := findDo(fdTmp, cwd, tgt)
                if err != nil {
                        break
                }
-               _, err = fdTmp.Seek(0, 0)
+               _, err = fdTmp.Seek(0, os.SEEK_SET)
                if err != nil {
                        break
                }
@@ -271,11 +337,21 @@ CmdSwitch:
                        }
                        fmt.Println(cwdMustRel(cwd, m["Target"]))
                }
-               ok = doFile != ""
-       case "tai64nlocal":
-               bw := bufio.NewWriter(os.Stdout)
-               err = tai64nLocal(bw, os.Stdin)
-               bw.Flush()
+               if doFile == "" {
+                       ok = false
+               } else {
+                       p := make([]string, 0, upLevels+2)
+                       p = append(p, cwd)
+                       for i := 0; i < upLevels; i++ {
+                               p = append(p, "..")
+                       }
+                       p = append(p, doFile)
+                       rel, err := filepath.Rel(Cwd, path.Join(p...))
+                       if err != nil {
+                               panic(err)
+                       }
+                       fmt.Println(rel)
+               }
        default:
                log.Fatalln("unknown command", cmdName)
        }