X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=run.go;h=bb455e845df4b20abc91be0a10c584367b43a301;hb=e14100898b08c312919f58f712f19f623f602748;hp=eb67304fea4de6fe8798c7e28823fdfbe71b6f9b;hpb=6ef14f9de82e4a61532b84b149bde0c953d58a04;p=goredo.git diff --git a/run.go b/run.go index eb67304..bb455e8 100644 --- a/run.go +++ b/run.go @@ -31,6 +31,7 @@ import ( "path" "strconv" "strings" + "sync" "syscall" "time" @@ -47,7 +48,6 @@ const ( EnvStderrKeep = "REDO_LOGS" EnvStderrSilent = "REDO_SILENT" EnvNoSync = "REDO_NO_SYNC" - EnvStampPrev = "REDO_STAMP_PREV" RedoDir = ".redo" LockSuffix = ".lock" @@ -57,12 +57,11 @@ const ( ) var ( - Trace bool = false NoSync bool = false StderrKeep bool = false StderrSilent bool = false StderrPrefix string - StampPrev string + Jobs sync.WaitGroup 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)") @@ -113,23 +112,24 @@ func tempfile(dir, prefix string) (*os.File, error) { return os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, os.FileMode(0666)) } -func isModified(cwd, redoDir, tgt string) (bool, error) { +func isModified(cwd, redoDir, tgt string) (bool, string, error) { fdDep, err := os.Open(path.Join(redoDir, tgt+DepSuffix)) if err != nil { if os.IsNotExist(err) { - return false, nil + return false, "", nil } - return false, err + return false, "", err } defer fdDep.Close() r := recfile.NewReader(fdDep) + var ourTs string for { m, err := r.NextMap() if err != nil { if err == io.EOF { break } - return false, err + return false, "", err } if m["Target"] != tgt { continue @@ -137,21 +137,21 @@ func isModified(cwd, redoDir, tgt string) (bool, error) { fd, err := os.Open(path.Join(cwd, tgt)) if err != nil { if os.IsNotExist(err) { - return false, nil + return false, "", nil } - return false, err + return false, "", err } defer fd.Close() - ourTs, err := fileCtime(fd) + ourTs, err = fileCtime(fd) if err != nil { - return false, err + return false, "", err } if ourTs != m["Ctime"] { - return true, nil + return true, ourTs, nil } break } - return false, nil + return false, ourTs, nil } func syncDir(dir string) error { @@ -164,7 +164,7 @@ func syncDir(dir string) error { return err } -func runScript(tgtOrig string, errs chan error, stampPrev string) error { +func runScript(tgtOrig string, errs chan error, traced bool) error { cwd, tgt := cwdAndTgt(tgtOrig) redoDir := path.Join(cwd, RedoDir) if err := mkdirs(redoDir); err != nil { @@ -227,7 +227,7 @@ func runScript(tgtOrig string, errs chan error, stampPrev string) error { } // Check if target is not modified externally - modified, err := isModified(cwd, redoDir, tgt) + modified, tsPrev, err := isModified(cwd, redoDir, tgt) if err != nil { lockRelease() return TgtErr{tgtOrig, err} @@ -235,8 +235,10 @@ func runScript(tgtOrig string, errs chan error, stampPrev string) error { if modified { trace(CWarn, "%s externally modified: not redoing", tgtOrig) lockRelease() - errs <- nil - return TgtErr{tgtOrig, err} + go func() { + errs <- nil + }() + return nil } // Start preparing .dep @@ -322,7 +324,7 @@ func runScript(tgtOrig string, errs chan error, stampPrev string) error { } else { // Shell cmdName = "/bin/sh" - if Trace { + if traced { args = append(args, "-ex") } else { args = append(args, "-e") @@ -347,10 +349,6 @@ func runScript(tgtOrig string, errs chan error, stampPrev string) error { 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", EnvStderrPrefix, childStderrPrefix, @@ -366,7 +364,9 @@ func runScript(tgtOrig string, errs chan error, stampPrev string) error { } else { cmd.ExtraFiles = append(cmd.ExtraFiles, JSR) cmd.ExtraFiles = append(cmd.ExtraFiles, JSW) - cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%d,%d", EnvJSFd, 3+fdNum+0, 3+fdNum+1)) + cmd.Env = append(cmd.Env, fmt.Sprintf( + "%s=%d,%d", EnvJSFd, 3+fdNum+0, 3+fdNum+1, + )) fdNum += 2 } @@ -458,6 +458,18 @@ func runScript(tgtOrig string, errs chan error, stampPrev string) error { return } + // Was $1 touched? + if fd, err := os.Open(path.Join(cwdOrig, tgt)); err == nil { + ts, err := fileCtime(fd) + fd.Close() + if err == nil && ts != tsPrev { + runErr.Err = errors.New("$1 was explicitly touched") + errs <- runErr + fd.Close() + return + } + } + // Does it produce both stdout and tmp? fiStdout, err := os.Stat(fdStdout.Name()) if err != nil { @@ -544,3 +556,15 @@ func runScript(tgtOrig string, errs chan error, stampPrev string) error { }() return nil } + +func isOkRun(err error) bool { + if err == nil { + return true + } + if err, ok := err.(RunErr); ok && err.Err == nil { + trace(CRedo, "%s", err.Name()) + return true + } + trace(CErr, "%s", err) + return false +}