X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=main.go;h=20072155f67c423ac294d82014af923f90f5280d;hb=fa0728d6bc790672982ba006961077371d2b552d;hp=d0d3ab282cac7bb30cbff76d4ff222f7ce82486a;hpb=bc7701e7a4f95cee680e0736ec3e68a8b0b5c09f;p=goredo.git diff --git a/main.go b/main.go index d0d3ab2..2007215 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,6 @@ /* -goredo -- redo implementation on pure Go -Copyright (C) 2020 Sergey Matveev +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 it under the terms of the GNU General Public License as published by @@ -28,39 +28,13 @@ import ( "path" "path/filepath" "strconv" - "sync" "go.cypherpunks.ru/recfile" - "golang.org/x/sys/unix" -) - -const ( - RedoLevelEnv = "REDO_LEVEL" - RedoDepFdEnv = "REDO_DEP_FD" - RedoDirPrefixEnv = "REDO_DIRPREFIX" - RedoBuildUUIDEnv = "REDO_BUILD_UUID" - RedoStderrPrefixEnv = "REDO_STDERR_PREFIX" - RedoJSRFdEnv = "REDO_JSR_FD" - RedoJSWFdEnv = "REDO_JSW_FD" ) var ( - Level = 0 - Trace bool = false - Force bool = false - NoHash bool = false - NoSync bool = false - Cwd string - Jobs sync.WaitGroup - - JobsN = flag.Uint("j", 1, "number of parallel jobs (0 for infinite)") - - StderrKeep bool = false - StderrSilent bool = false - StderrPrefix string - + Cwd string BuildUUID string - IsMaster bool = false ) func mustSetenv(key, value string) { @@ -82,17 +56,9 @@ func mustParseFd(v, name string) *os.File { } func main() { - xflag := flag.Bool("x", false, "trace current target (sh -x) (set REDO_TRACE=1 for others too)") - stderrKeep := flag.Bool("stderr-keep", false, "keep job's stderr (REDO_STDERR_KEEP=1)") - stderrSilent := flag.Bool("stderr-silent", false, "do not print job's stderr (REDO_STDERR_SILENT=1)") - debug := flag.Bool("debug", false, "enable debug logging (REDO_DEBUG=1)") - logWait := flag.Bool("log-wait", false, "enable wait messages logging (REDO_LOG_WAIT=1)") - logLock := flag.Bool("log-lock", false, "enable lock messages logging (REDO_LOG_LOCK=1)") - logPid := flag.Bool("log-pid", false, "append PIDs (REDO_LOG_PID=1)") - logJS := flag.Bool("log-js", false, "enable jobserver messages logging (REDO_LOG_JS=1)") 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() @@ -105,125 +71,157 @@ func main() { return } if *symlinks { + rc := 0 for _, cmdName := range []string{ "redo", "redo-always", "redo-cleanup", + "redo-dot", "redo-ifchange", "redo-ifcreate", "redo-log", "redo-stamp", "redo-whichdo", } { + fmt.Println(os.Args[0], "<-", cmdName) if err := os.Symlink(os.Args[0], cmdName); err != nil { - log.Fatalln(err) + rc = 1 + log.Println(err) } } - return + 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("NO_COLOR") != "" - NoHash = os.Getenv("REDO_NO_HASH") == "1" - NoSync = os.Getenv("REDO_NO_SYNC") == "1" + NoColor = os.Getenv(EnvNoColor) != "" + NoSync = os.Getenv(EnvNoSync) == "1" + InodeTrust = os.Getenv(EnvInodeNoTrust) == "" - TopDir = os.Getenv("REDO_TOP_DIR") - if TopDir != "" { + TopDir = os.Getenv(EnvTopDir) + if TopDir == "" { + TopDir = "/" + } else { TopDir, err = filepath.Abs(TopDir) if err != nil { panic(err) } } + DirPrefix = os.Getenv(EnvDirPrefix) - if *stderrKeep { - mustSetenv("REDO_STDERR_KEEP", "1") + if *flagStderrKeep { + mustSetenv(EnvStderrKeep, "1") + } + if *flagStderrSilent { + mustSetenv(EnvStderrSilent, "1") } - if *stderrSilent { - mustSetenv("REDO_STDERR_SILENT", "1") + if *flagNoProgress { + mustSetenv(EnvNoProgress, "1") } - if *debug { - mustSetenv("REDO_DEBUG", "1") + if *flagDebug { + mustSetenv(EnvDebug, "1") } - if *logWait { - mustSetenv("REDO_LOG_WAIT", "1") + if *flagLogWait { + mustSetenv(EnvLogWait, "1") } - if *logLock { - mustSetenv("REDO_LOG_LOCK", "1") + if *flagLogLock { + mustSetenv(EnvLogLock, "1") } - if *logPid { - mustSetenv("REDO_LOG_PID", "1") + if *flagLogPid { + mustSetenv(EnvLogPid, "1") } - if *logJS { - mustSetenv("REDO_LOG_JS", "1") + if *flagLogJS { + mustSetenv(EnvLogJS, "1") } - StderrKeep = os.Getenv("REDO_STDERR_KEEP") == "1" - StderrSilent = os.Getenv("REDO_STDERR_SILENT") == "1" - Debug = os.Getenv("REDO_DEBUG") == "1" - LogWait = os.Getenv("REDO_LOG_WAIT") == "1" - LogLock = os.Getenv("REDO_LOG_LOCK") == "1" - LogJS = os.Getenv("REDO_LOG_JS") == "1" - if Debug || os.Getenv("REDO_LOG_PID") == "1" { + 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" + LogJS = os.Getenv(EnvLogJS) == "1" + if Debug || os.Getenv(EnvLogPid) == "1" { MyPid = os.Getpid() } - if *xflag { - Trace = true + var traced bool + if *flagTraceAll { + mustSetenv(EnvTrace, "1") + } + if *flagTrace { + traced = true } else { - Trace = os.Getenv("REDO_TRACE") == "1" + traced = os.Getenv(EnvTrace) == "1" } // Those are internal envs - StderrPrefix = os.Getenv(RedoStderrPrefixEnv) - if v := os.Getenv(RedoLevelEnv); v != "" { - level, err := strconv.ParseUint(v, 10, 64) + StderrPrefix = os.Getenv(EnvStderrPrefix) + if v := os.Getenv(EnvLevel); v != "" { + Level, err = strconv.Atoi(v) if err != nil { panic(err) } - Level = int(level) + if Level < 0 { + panic("negative " + EnvLevel) + } } var fdDep *os.File - if v := os.Getenv(RedoDepFdEnv); v != "" { - fdDep = mustParseFd(v, RedoDepFdEnv) + if v := os.Getenv(EnvDepFd); v != "" { + fdDep = mustParseFd(v, EnvDepFd) } - BuildUUID = os.Getenv(RedoBuildUUIDEnv) + BuildUUID = os.Getenv(EnvBuildUUID) + tgts := flag.Args() if BuildUUID == "" { - IsMaster = true 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 { case "redo": - Force = true - ok, err = ifchange(tgts) + for _, tgt := range tgts { + ok, err = ifchange([]string{tgt}, true, traced) + if err != nil || !ok { + break + } + } case "redo-ifchange": - ok, err = ifchange(tgts) - writeDeps(fdDep, tgts) + ok, err = ifchange(tgts, false, traced) + if err == nil { + err = writeDeps(fdDep, tgts) + } case "redo-ifcreate": if fdDep == nil { - log.Fatalln("no", RedoDepFdEnv) + log.Fatalln("no", EnvDepFd) } for _, tgt := range tgts { err = ifcreate(fdDep, tgt) @@ -233,7 +231,7 @@ CmdSwitch: } case "redo-always": if fdDep == nil { - log.Fatalln("no", RedoDepFdEnv) + log.Fatalln("no", EnvDepFd) } err = always(fdDep) case "redo-cleanup": @@ -243,9 +241,11 @@ CmdSwitch: break } } + case "redo-dot": + err = dotPrint(tgts) case "redo-stamp": if fdDep == nil { - log.Fatalln("no", RedoDepFdEnv) + log.Fatalln("no", EnvDepFd) } err = stamp(fdDep, os.Stdin) case "redo-log": @@ -269,13 +269,15 @@ CmdSwitch: break } os.Remove(fdTmp.Name()) - var doFile string 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) if err != nil { break } - fdTmp.Seek(0, 0) r := recfile.NewReader(fdTmp) for { m, err := r.NextMap() @@ -285,13 +287,23 @@ CmdSwitch: } break CmdSwitch } - rel, err := filepath.Rel(Cwd, path.Join(cwd, m["Target"])) + fmt.Println(cwdMustRel(cwd, m["Target"])) + } + 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) } - ok = doFile != "" default: log.Fatalln("unknown command", cmdName) }