X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=run.go;h=eb67304fea4de6fe8798c7e28823fdfbe71b6f9b;hb=6ef14f9de82e4a61532b84b149bde0c953d58a04;hp=58b9f6daff2fa933a17c6ff906766676169c86dd;hpb=bc7701e7a4f95cee680e0736ec3e68a8b0b5c09f;p=goredo.git diff --git a/run.go b/run.go index 58b9f6d..eb67304 100644 --- a/run.go +++ b/run.go @@ -23,6 +23,7 @@ import ( "bufio" "encoding/hex" "errors" + "flag" "fmt" "io" "os" @@ -38,6 +39,16 @@ import ( ) const ( + EnvDepFd = "REDO_DEP_FD" + EnvDirPrefix = "REDO_DIRPREFIX" + EnvBuildUUID = "REDO_BUILD_UUID" + EnvStderrPrefix = "REDO_STDERR_PREFIX" + EnvTrace = "REDO_TRACE" + EnvStderrKeep = "REDO_LOGS" + EnvStderrSilent = "REDO_SILENT" + EnvNoSync = "REDO_NO_SYNC" + EnvStampPrev = "REDO_STAMP_PREV" + RedoDir = ".redo" LockSuffix = ".lock" DepSuffix = ".dep" @@ -45,6 +56,46 @@ const ( LogSuffix = ".log" ) +var ( + Trace bool = false + NoSync bool = false + StderrKeep bool = false + StderrSilent bool = false + StderrPrefix string + StampPrev string + + flagTrace = flag.Bool("x", false, "trace current target (sh -x) (set REDO_TRACE=1 for others too)") + flagStderrKeep = flag.Bool("logs", false, "keep job's stderr (REDO_LOGS=1)") + flagStderrSilent = flag.Bool("silent", false, "do not print job's stderr (REDO_SILENT=1)") +) + +type RunErr struct { + Tgt string + DoFile string + Started *time.Time + Finished *time.Time + Err error +} + +func (e RunErr) Unwrap() error { return e.Err } + +func (e *RunErr) Name() string { + var name string + if e.DoFile == "" { + name = e.Tgt + } else { + name = fmt.Sprintf("%s (%s)", e.Tgt, e.DoFile) + } + if e.Finished == nil { + return name + } + return fmt.Sprintf("%s (%fsec)", name, e.Finished.Sub(*e.Started).Seconds()) +} + +func (e RunErr) Error() string { + return fmt.Sprintf("%s: %s", e.Name(), e.Err) +} + func mkdirs(pth string) error { if _, err := os.Stat(pth); err == nil { return nil @@ -103,33 +154,6 @@ func isModified(cwd, redoDir, tgt string) (bool, error) { return false, nil } -type RunErr struct { - Tgt string - DoFile string - Started *time.Time - Finished *time.Time - Err error -} - -func (e RunErr) Unwrap() error { return e.Err } - -func (e *RunErr) Name() string { - var name string - if e.DoFile == "" { - name = e.Tgt - } else { - name = fmt.Sprintf("%s (%s)", e.Tgt, e.DoFile) - } - if e.Finished == nil { - return name - } - return fmt.Sprintf("%s (%fsec)", name, e.Finished.Sub(*e.Started).Seconds()) -} - -func (e RunErr) Error() string { - return fmt.Sprintf("%s: %s", e.Name(), e.Err) -} - func syncDir(dir string) error { fd, err := os.Open(dir) if err != nil { @@ -140,9 +164,8 @@ func syncDir(dir string) error { return err } -func runScript(tgt string, errs chan error) error { - tgtOrig := tgt - cwd, tgt := cwdAndTgt(tgt) +func runScript(tgtOrig string, errs chan error, stampPrev string) error { + cwd, tgt := cwdAndTgt(tgtOrig) redoDir := path.Join(cwd, RedoDir) if err := mkdirs(redoDir); err != nil { return TgtErr{tgtOrig, err} @@ -178,20 +201,21 @@ func runScript(tgt string, errs chan error) error { unix.Flock(int(fdLock.Fd()), unix.LOCK_EX) lockRelease() trace(CDebug, "waiting done: %s", tgtOrig) - var builtNow bool + var depInfo *DepInfo fdDep, err := os.Open(path.Join(redoDir, tgt+DepSuffix)) if err != nil { if os.IsNotExist(err) { - err = errors.New("was not built") + err = errors.New("was not built: no .dep") } goto Finish } - builtNow, _, err = isBuiltNow(fdDep) + defer fdDep.Close() + depInfo, err = depRead(fdDep) if err != nil { goto Finish } - if !builtNow { - err = errors.New("was not built") + if depInfo.build != BuildUUID { + err = errors.New("was not built: build differs") } Finish: if err != nil { @@ -319,29 +343,31 @@ func runScript(tgt string, errs chan error) error { cmd := exec.Command(cmdName, args...) cmd.Dir = cwd cmd.Stdout = fdStdout - cmd.Env = append(os.Environ(), fmt.Sprintf("%s=%d", RedoLevelEnv, Level+1)) - cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", RedoDirPrefixEnv, dirPrefix)) - cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", RedoBuildUUIDEnv, BuildUUID)) + cmd.Env = append(os.Environ(), fmt.Sprintf("%s=%d", EnvLevel, Level+1)) + cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", EnvDirPrefix, dirPrefix)) + cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", EnvBuildUUID, BuildUUID)) + + if stampPrev != "" { + cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", EnvStampPrev, stampPrev)) + } + childStderrPrefix := tempsuffix() cmd.Env = append(cmd.Env, fmt.Sprintf( - "%s=%s", RedoStderrPrefixEnv, childStderrPrefix, + "%s=%s", EnvStderrPrefix, childStderrPrefix, )) cmd.ExtraFiles = append(cmd.ExtraFiles, fdDep) fdNum := 0 - cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%d", RedoDepFdEnv, 3+fdNum)) + cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%d", EnvDepFd, 3+fdNum)) fdNum++ if JSR == nil { // infinite jobs - cmd.Env = append(cmd.Env, fmt.Sprintf("%s=NO", RedoJSRFdEnv)) - cmd.Env = append(cmd.Env, fmt.Sprintf("%s=NO", RedoJSWFdEnv)) + cmd.Env = append(cmd.Env, fmt.Sprintf("%s=NO", EnvJSFd)) } else { cmd.ExtraFiles = append(cmd.ExtraFiles, JSR) cmd.ExtraFiles = append(cmd.ExtraFiles, JSW) - cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%d", RedoJSRFdEnv, 3+fdNum)) - fdNum++ - cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%d", RedoJSWFdEnv, 3+fdNum)) - fdNum++ + cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%d,%d", EnvJSFd, 3+fdNum+0, 3+fdNum+1)) + fdNum += 2 } // Preparing stderr