]> Cypherpunks.ru repositories - goredo.git/blobdiff - run.go
Trace only non-dependant targets
[goredo.git] / run.go
diff --git a/run.go b/run.go
index eb67304fea4de6fe8798c7e28823fdfbe71b6f9b..bb455e845df4b20abc91be0a10c584367b43a301 100644 (file)
--- 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
+}