X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=run.go;h=0178d726b9d9b476dbd01d1db45e713d0f5c80c0;hb=4274dce3366cee45bfaccbe5ca340ce6efe68e00;hp=d31c8a0c5a4ffb52816cb74d90de5536c8fe515b;hpb=46e189a9c6398c1ab1245ab1e9827b959db29219;p=goredo.git diff --git a/run.go b/run.go index d31c8a0..0178d72 100644 --- a/run.go +++ b/run.go @@ -52,11 +52,12 @@ const ( EnvStderrSilent = "REDO_SILENT" EnvNoSync = "REDO_NO_SYNC" - RedoDir = ".redo" - LockSuffix = ".lock" - DepSuffix = ".rec" - TmpPrefix = ".redo." - LogSuffix = ".log" + RedoDir = ".redo" + LockSuffix = ".lock" + DepSuffix = ".rec" + TmpPrefix = ".redo." + LogSuffix = ".log" + LogRecSuffix = ".log-rec" ) var ( @@ -72,6 +73,9 @@ var ( flagStderrSilent *bool TracedAll bool + + RunningProcs = map[int]*os.Process{} + RunningProcsM sync.Mutex ) func init() { @@ -139,7 +143,7 @@ func isModified(cwd, redoDir, tgt string) (bool, *Inode, error) { } return false, nil, err } - if m["Target"] != tgt { + if m["Type"] != DepTypeIfchange || m["Target"] != tgt { continue } fd, err := os.Open(path.Join(cwd, tgt)) @@ -384,14 +388,13 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { if StderrKeep { fdStderr, err = os.OpenFile( path.Join(redoDir, tgt+LogSuffix), - os.O_WRONLY|os.O_CREATE, + os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.FileMode(0666), ) if err != nil { cleanup() return TgtErr{tgtOrig, err} } - fdStderr.Truncate(0) } shCtx := fmt.Sprintf( "sh: %s: %s %s cwd:%s dirprefix:%s", @@ -408,10 +411,11 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { } else { cmd.ExtraFiles = append(cmd.ExtraFiles, JSR) cmd.ExtraFiles = append(cmd.ExtraFiles, JSW) - cmd.Env = append(cmd.Env, fmt.Sprintf( - "%s=%s %s%d,%d", - MakeFlagsName, MakeFlags, MakeJSArg, 3+fdNum+0, 3+fdNum+1, - )) + makeFlags := fmt.Sprintf( + "%s %s%d,%d", MakeFlags, MakeJSArg, 3+fdNum+0, 3+fdNum+1, + ) + makeFlags = strings.Trim(makeFlags, " ") + cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", MakeFlagsName, makeFlags)) fdNum += 2 cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%d", EnvJSToken, jsToken)) } @@ -448,19 +452,22 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { fdStdout.Close() if fdStderr != nil { fdStderr.Close() - logRecPath := path.Join(redoDir, tgt+LogSuffix+DepSuffix) + logRecPath := path.Join(redoDir, tgt+LogRecSuffix) if fdStderr, err = os.OpenFile( logRecPath, - os.O_WRONLY|os.O_CREATE, + os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.FileMode(0666), ); err == nil { - fdStderr.Truncate(0) fields := []recfile.Field{ {Name: "Build", Value: BuildUUID}, - {Name: "PID", Value: strconv.Itoa(cmd.Process.Pid)}, {Name: "PPID", Value: strconv.Itoa(os.Getpid())}, {Name: "Cwd", Value: cwd}, } + if cmd.Process != nil { + fields = append(fields, recfile.Field{ + Name: "PID", Value: strconv.Itoa(cmd.Process.Pid), + }) + } ts := new(tai64n.TAI64N) ts.FromTime(started) fields = append(fields, @@ -475,7 +482,7 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { }) fields = append(fields, recfile.Field{Name: "Cmd", Value: cmdName}) for _, arg := range args { - fields = append(fields, recfile.Field{Name: "Cmd", Value: arg}) + fields = append(fields, recfile.Field{Name: "Arg", Value: arg}) } for _, env := range cmd.Env { fields = append(fields, recfile.Field{Name: "Env", Value: env}) @@ -489,7 +496,7 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { w := bufio.NewWriter(fdStderr) var depInfo *DepInfo - fdDep, err = os.Open(fdDep.Name()) + fdDep, err := os.Open(fdDepPath) if err != nil { goto Err } @@ -542,6 +549,9 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { errs <- runErr return } + RunningProcsM.Lock() + RunningProcs[cmd.Process.Pid] = cmd.Process + RunningProcsM.Unlock() pid := fmt.Sprintf("[%d]", cmd.Process.Pid) trace(CDebug, "%s runs %s", tgtOrig, pid) @@ -578,6 +588,9 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { // Wait for job completion <-stderrTerm err = cmd.Wait() + RunningProcsM.Lock() + delete(RunningProcs, cmd.Process.Pid) + RunningProcsM.Unlock() finished = time.Now() runErr.Finished = &finished if err != nil { @@ -588,6 +601,29 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { } // Was $1 touched? + if fd, err := os.Open(path.Join(cwdOrig, tgt)); err == nil { + errTouched := errors.New("$1 was explicitly touched") + if inodePrev == nil { + fd.Close() + runErr.Err = errTouched + errs <- runErr + return + } else { + inode, err := inodeFromFile(fd) + fd.Close() + if err != nil { + runErr.Err = err + errs <- runErr + return + } + if !inode.Equals(inodePrev) { + runErr.Err = errTouched + errs <- runErr + return + } + } + } + if inodePrev != nil { if fd, err := os.Open(path.Join(cwdOrig, tgt)); err == nil { inode, err := inodeFromFile(fd) @@ -671,7 +707,8 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { goto Finish } } - err = os.Rename(fdDep.Name(), path.Join(redoDir, tgt+DepSuffix)) + fdDepPath = path.Join(redoDir, tgt+DepSuffix) + err = os.Rename(fdDep.Name(), fdDepPath) if err != nil { goto Finish }