X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=main.go;h=634ca8fdff584f78140f35f4db8d178c58894d69;hb=b69d2ab11a495413ecc16a9bfea0d105b030c606;hp=c3b1be78677b731291db45ca8af4cfab7b74a5d3;hpb=9485b9805119a388f1d4d93d18b0fe1a2da212a0;p=goredo.git diff --git a/main.go b/main.go index c3b1be7..634ca8f 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,6 @@ /* goredo -- djb's redo implementation on pure Go -Copyright (C) 2020-2021 Sergey Matveev +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 @@ -21,10 +21,10 @@ import ( "bufio" "bytes" "crypto/rand" + "errors" "flag" "fmt" "io" - "io/ioutil" "log" "os" "os/signal" @@ -54,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) } } @@ -111,6 +114,7 @@ func main() { CmdNameRedoAffects, CmdNameRedoAlways, CmdNameRedoCleanup, + CmdNameRedoDepFix, CmdNameRedoDot, CmdNameRedoIfchange, CmdNameRedoIfcreate, @@ -131,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 = "/" @@ -154,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" @@ -189,7 +192,7 @@ func main() { } var traced bool if flagTraceAll != nil && *flagTraceAll { - mustSetenv(EnvTrace, "1") + mustSetenv(EnvTrace) } if os.Getenv(EnvTrace) == "1" { TracedAll = true @@ -197,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) } @@ -217,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) @@ -235,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) } } @@ -284,23 +308,23 @@ func main() { } } - killed := make(chan os.Signal, 0) + killed := make(chan os.Signal, 1) signal.Notify(killed, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM) go func() { <-killed - trace(CDebug, "[%s] killed", BuildUUID) + tracef(CDebug, "[%s] killed", BuildUUID) jsReleaseAll() RunningProcsM.Lock() for pid, proc := range RunningProcs { - trace(CDebug, "[%s] killing child %d", BuildUUID, pid) - proc.Signal(syscall.SIGTERM) + 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, ) @@ -315,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 { @@ -325,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 @@ -366,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 } @@ -386,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 @@ -477,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) } @@ -487,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) }