]> Cypherpunks.ru repositories - goredo.git/blobdiff - main.go
Redundant @documentencoding
[goredo.git] / main.go
diff --git a/main.go b/main.go
index 67c428c14a6b6661bdc9bf94ae4dac0a0cf1062b..634ca8fdff584f78140f35f4db8d178c58894d69 100644 (file)
--- a/main.go
+++ b/main.go
@@ -1,6 +1,6 @@
 /*
 goredo -- djb's redo implementation on pure Go
-Copyright (C) 2020-2021 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2020-2023 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
@@ -21,17 +21,19 @@ import (
        "bufio"
        "bytes"
        "crypto/rand"
+       "errors"
        "flag"
        "fmt"
        "io"
-       "io/ioutil"
        "log"
        "os"
+       "os/signal"
        "path"
        "path/filepath"
        "runtime"
        "sort"
        "strconv"
+       "syscall"
 
        "go.cypherpunks.ru/recfile"
        "golang.org/x/sys/unix"
@@ -52,16 +54,19 @@ const (
        CmdNameRedoStamp    = "redo-stamp"
        CmdNameRedoTargets  = "redo-targets"
        CmdNameRedoWhichdo  = "redo-whichdo"
+       CmdNameRedoDepFix   = "redo-depfix"
+       CmdNameRedoInode    = "redo-inode"
 )
 
 var (
        Cwd       string
        BuildUUID string
        IsTopRedo bool // is it the top redo instance
+       UmaskCur  int
 )
 
-func mustSetenv(key, value string) {
-       if err := os.Setenv(key, value); err != nil {
+func mustSetenv(key string) {
+       if err := os.Setenv(key, "1"); err != nil {
                panic(err)
        }
 }
@@ -109,6 +114,7 @@ func main() {
                        CmdNameRedoAffects,
                        CmdNameRedoAlways,
                        CmdNameRedoCleanup,
+                       CmdNameRedoDepFix,
                        CmdNameRedoDot,
                        CmdNameRedoIfchange,
                        CmdNameRedoIfcreate,
@@ -129,16 +135,15 @@ func main() {
        }
        log.SetFlags(log.Lshortfile)
 
+       UmaskCur = syscall.Umask(0)
+       syscall.Umask(UmaskCur)
+
        var err error
        Cwd, err = os.Getwd()
        if err != nil {
                log.Fatalln(err)
        }
 
-       NoColor = os.Getenv(EnvNoColor) != ""
-       NoSync = os.Getenv(EnvNoSync) == "1"
-       InodeTrust = os.Getenv(EnvInodeNoTrust) == ""
-
        TopDir = os.Getenv(EnvTopDir)
        if TopDir == "" {
                TopDir = "/"
@@ -152,28 +157,28 @@ func main() {
        DepCwd = os.Getenv(EnvDepCwd)
 
        if flagStderrKeep != nil && *flagStderrKeep {
-               mustSetenv(EnvStderrKeep, "1")
+               mustSetenv(EnvStderrKeep)
        }
        if flagStderrSilent != nil && *flagStderrSilent {
-               mustSetenv(EnvStderrSilent, "1")
+               mustSetenv(EnvStderrSilent)
        }
        if flagNoProgress != nil && *flagNoProgress {
-               mustSetenv(EnvNoProgress, "1")
+               mustSetenv(EnvNoProgress)
        }
        if flagDebug != nil && *flagDebug {
-               mustSetenv(EnvDebug, "1")
+               mustSetenv(EnvDebug)
        }
        if flagLogWait != nil && *flagLogWait {
-               mustSetenv(EnvLogWait, "1")
+               mustSetenv(EnvLogWait)
        }
        if flagLogLock != nil && *flagLogLock {
-               mustSetenv(EnvLogLock, "1")
+               mustSetenv(EnvLogLock)
        }
        if flagLogPid != nil && *flagLogPid {
-               mustSetenv(EnvLogPid, "1")
+               mustSetenv(EnvLogPid)
        }
        if flagLogJS != nil && *flagLogJS {
-               mustSetenv(EnvLogJS, "1")
+               mustSetenv(EnvLogJS)
        }
        StderrKeep = os.Getenv(EnvStderrKeep) == "1"
        StderrSilent = os.Getenv(EnvStderrSilent) == "1"
@@ -187,7 +192,7 @@ func main() {
        }
        var traced bool
        if flagTraceAll != nil && *flagTraceAll {
-               mustSetenv(EnvTrace, "1")
+               mustSetenv(EnvTrace)
        }
        if os.Getenv(EnvTrace) == "1" {
                TracedAll = true
@@ -195,16 +200,30 @@ func main() {
        } else if flagTrace != nil {
                traced = *flagTrace
        }
+       NoColor = os.Getenv(EnvNoColor) != ""
+       NoSync = os.Getenv(EnvNoSync) == "1"
+       StopIfMod = os.Getenv(EnvStopIfMod) == "1"
+       switch s := os.Getenv(EnvInodeTrust); s {
+       case "none":
+               InodeTrust = InodeTrustNone
+       case "", "ctime":
+               InodeTrust = InodeTrustCtime
+       case "mtime":
+               InodeTrust = InodeTrustMtime
+       default:
+               log.Fatalln("unknown", EnvInodeTrust, "value")
+       }
+       tracef(CDebug, "inode-trust: %s", InodeTrust)
 
        // Those are internal envs
-       FdOODTgts, err = ioutil.TempFile("", "ood-tgts")
+       FdOODTgts, err = os.CreateTemp("", "ood-tgts")
        if err != nil {
                log.Fatalln(err)
        }
        if err = os.Remove(FdOODTgts.Name()); err != nil {
                log.Fatalln(err)
        }
-       FdOODTgtsLock, err = ioutil.TempFile("", "ood-tgts.lock")
+       FdOODTgtsLock, err = os.CreateTemp("", "ood-tgts.lock")
        if err != nil {
                log.Fatalln(err)
        }
@@ -215,17 +234,24 @@ func main() {
        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 {
+               flock := unix.Flock_t{
+                       Type:   unix.F_WRLCK,
+                       Whence: io.SeekStart,
+               }
+               if err = unix.FcntlFlock(fdLock.Fd(), unix.F_SETLKW, &flock); err != nil {
                        log.Fatalln(err)
                }
                if _, err = fd.Seek(0, io.SeekStart); err != nil {
                        log.Fatalln(err)
                }
-               tgtsRaw, err := ioutil.ReadAll(bufio.NewReader(fd))
+               tgtsRaw, err := io.ReadAll(bufio.NewReader(fd))
                if err != nil {
                        log.Fatalln(err)
                }
-               unix.Flock(int(fdLock.Fd()), unix.LOCK_UN)
+               flock.Type = unix.F_UNLCK
+               if err = unix.FcntlFlock(fdLock.Fd(), unix.F_SETLK, &flock); err != nil {
+                       log.Fatalln(err)
+               }
                OODTgts = map[string]struct{}{}
                for _, tgtRaw := range bytes.Split(tgtsRaw, []byte{0}) {
                        t := string(tgtRaw)
@@ -233,7 +259,7 @@ func main() {
                                continue
                        }
                        OODTgts[t] = struct{}{}
-                       trace(CDebug, "ood: known to be: %s", t)
+                       tracef(CDebug, "ood: known to be: %s", t)
                }
        }
 
@@ -282,9 +308,23 @@ func main() {
                }
        }
 
+       killed := make(chan os.Signal, 1)
+       signal.Notify(killed, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)
+       go func() {
+               <-killed
+               tracef(CDebug, "[%s] killed", BuildUUID)
+               jsReleaseAll()
+               RunningProcsM.Lock()
+               for pid, proc := range RunningProcs {
+                       tracef(CDebug, "[%s] killing child %d", BuildUUID, pid)
+                       _ = proc.Signal(syscall.SIGTERM)
+               }
+               os.Exit(1)
+       }()
+
        ok := true
        err = nil
-       trace(
+       tracef(
                CDebug, "[%s] run: %s %s cwd:%s dirprefix:%s",
                BuildUUID, cmdName, tgts, Cwd, DirPrefix,
        )
@@ -299,9 +339,9 @@ CmdSwitch:
                        }
                }
        case CmdNameRedoIfchange:
-               ok, err = ifchange(tgts, false, traced)
+               ok, err = ifchange(tgts, *flagForcedIfchange, traced)
                if err == nil {
-                       err = writeDeps(fdDep, tgts)
+                       err = depsWrite(fdDep, tgts)
                }
        case CmdNameRedoIfcreate:
                if fdDep == nil {
@@ -309,8 +349,8 @@ CmdSwitch:
                }
                for _, tgt := range tgts {
                        tgtRel, err := filepath.Rel(
-                               filepath.Join(Cwd, DirPrefix),
-                               filepath.Join(Cwd, tgt),
+                               path.Join(Cwd, DirPrefix),
+                               path.Join(Cwd, tgt),
                        )
                        if err != nil {
                                break
@@ -350,7 +390,7 @@ CmdSwitch:
                        log.Fatalln("single target expected")
                }
                var fdTmp *os.File
-               fdTmp, err = ioutil.TempFile("", "whichdo")
+               fdTmp, err = os.CreateTemp("", "whichdo")
                if err != nil {
                        break
                }
@@ -370,7 +410,7 @@ CmdSwitch:
                for {
                        m, err := r.NextMap()
                        if err != nil {
-                               if err == io.EOF {
+                               if errors.Is(err, io.EOF) {
                                        break
                                }
                                break CmdSwitch
@@ -461,6 +501,22 @@ CmdSwitch:
                for _, src := range srcs {
                        fmt.Println(src)
                }
+       case CmdNameRedoDepFix:
+               err = depFix(Cwd)
+       case CmdNameRedoInode:
+               var inode *Inode
+               for _, tgt := range tgts {
+                       inode, err = inodeFromFileByPath(tgt)
+                       if err != nil {
+                               break
+                       }
+                       err = recfileWrite(os.Stdout, append(
+                               []recfile.Field{{Name: "Target", Value: tgt}},
+                               inode.RecfileFields()...)...)
+                       if err != nil {
+                               break
+                       }
+               }
        default:
                log.Fatalln("unknown command", cmdName)
        }
@@ -471,6 +527,6 @@ CmdSwitch:
        if !ok || err != nil {
                rc = 1
        }
-       trace(CDebug, "[%s] finished: %s %s", BuildUUID, cmdName, tgts)
+       tracef(CDebug, "[%s] finished: %s %s", BuildUUID, cmdName, tgts)
        os.Exit(rc)
 }