"time"
"go.cypherpunks.ru/recfile"
- "go.cypherpunks.ru/tai64n"
+ "go.cypherpunks.ru/tai64n/v2"
"golang.org/x/sys/unix"
)
const (
EnvDepFd = "REDO_DEP_FD"
EnvDirPrefix = "REDO_DIRPREFIX"
+ EnvDepCwd = "REDO_DEP_CWD"
EnvBuildUUID = "REDO_BUILD_UUID"
EnvStderrPrefix = "REDO_STDERR_PREFIX"
EnvTrace = "REDO_TRACE"
RedoDir = ".redo"
LockSuffix = ".lock"
- DepSuffix = ".dep"
+ DepSuffix = ".rec"
TmpPrefix = ".redo."
LogSuffix = ".log"
)
flagTraceAll = flag.Bool("xx", false, fmt.Sprintf("trace (sh -x) all targets (%s=1)", EnvTrace))
flagStderrKeep = flag.Bool("logs", false, fmt.Sprintf("keep job's stderr (%s=1)", EnvStderrKeep))
flagStderrSilent = flag.Bool("silent", false, fmt.Sprintf("do not print job's stderr (%s=1)", EnvStderrSilent))
+
+ TracedAll bool
)
type RunErr struct {
if e.Finished == nil {
return name
}
- return fmt.Sprintf("%s (%fsec)", name, e.Finished.Sub(*e.Started).Seconds())
+ return fmt.Sprintf("%s (%.3fs)", name, e.Finished.Sub(*e.Started).Seconds())
}
func (e RunErr) Error() string {
fdDep, err := os.Open(path.Join(redoDir, tgt+DepSuffix))
if err != nil {
if os.IsNotExist(err) {
- err = errors.New("was not built: no .dep")
+ err = errors.New("was not built: no .rec")
}
goto Finish
}
return nil
}
- // Start preparing .dep
+ // Start preparing .rec
fdDep, err := tempfile(redoDir, tgt+DepSuffix)
if err != nil {
lockRelease()
return TgtErr{tgtOrig, err}
}
+ fdDepPath := fdDep.Name()
cleanup := func() {
lockRelease()
fdDep.Close()
cleanup()
return TgtErr{tgtOrig, err}
}
+ fdDep.Close()
trace(CWait, "%s", runErr.Name())
// Prepare command line
args = make([]string, 0, 3)
} else {
cmdName = "/bin/sh"
- if traced {
+ if traced || TracedAll {
args = append(args, "-ex")
} else {
args = append(args, "-e")
cleanup()
return TgtErr{tgtOrig, err}
}
- tmpPath := fdStdout.Name() + ".3" // and for $3
+ stdoutPath := fdStdout.Name()
+ fdStdout.Close()
+ tmpPath := stdoutPath + ".3" // and for $3
tmpPathRel, err := filepath.Rel(cwd, tmpPath)
if err != nil {
panic(err)
cmd := exec.Command(cmdName, args...)
cmd.Dir = cwd
- cmd.Stdout = fdStdout
// cmd.Stdin reads from /dev/null by default
cmd.Env = append(os.Environ(), fmt.Sprintf("%s=%d", EnvLevel, Level+1))
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", EnvDirPrefix, dirPrefix))
))
fdNum := 0
- cmd.ExtraFiles = append(cmd.ExtraFiles, fdDep)
- cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%d", EnvDepFd, 3+fdNum))
+ cmd.ExtraFiles = append(cmd.ExtraFiles, FdOODTgts)
+ cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%d", EnvOODTgtsFd, 3+fdNum))
+ fdNum++
+ cmd.ExtraFiles = append(cmd.ExtraFiles, FdOODTgtsLock)
+ cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%d", EnvOODTgtsLockFd, 3+fdNum))
fdNum++
if FdStatus == nil {
fdNum++
}
- if JSR == nil {
- // infinite jobs
- 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,%d", EnvJSFd, 3+fdNum+0, 3+fdNum+1,
- ))
- fdNum += 2
- }
-
// Preparing stderr
- stderr, err := cmd.StderrPipe()
- if err != nil {
- panic(err)
- }
var fdStderr *os.File
if StderrKeep {
fdStderr, err = os.OpenFile(
Jobs.Add(1)
go func() {
- jsAcquire(shCtx)
+ jsToken := jsAcquire(shCtx)
+ if JSR == nil {
+ // infinite jobs
+ cmd.Env = append(cmd.Env, fmt.Sprintf("%s=NO", EnvJobs))
+ } 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,
+ ))
+ fdNum += 2
+ cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%d", EnvJSToken, jsToken))
+ }
+
if FdStatus != nil {
FdStatus.Write([]byte{StatusRun})
}
+
+ started := time.Now()
+ runErr.Started = &started
+ fdStdout, err = os.OpenFile(stdoutPath, os.O_RDWR, os.FileMode(0666))
+ if err != nil {
+ runErr.Err = err
+ errs <- runErr
+ return
+ }
+ cmd.Stdout = fdStdout
+ fdDep, err = os.OpenFile(fdDepPath, os.O_WRONLY|os.O_APPEND, os.FileMode(0666))
+ if err != nil {
+ runErr.Err = err
+ errs <- runErr
+ return
+ }
+ cmd.ExtraFiles = append(cmd.ExtraFiles, fdDep)
+ cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%d", EnvDepFd, 3+fdNum))
+ fdNum++
+ cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", EnvDepCwd, cwd))
+
defer func() {
- jsRelease(shCtx)
+ jsRelease(shCtx, jsToken)
lockRelease()
fdDep.Close()
fdStdout.Close()
}
Jobs.Done()
}()
- started := time.Now()
- runErr.Started = &started
- err := cmd.Start()
+ stderr, err := cmd.StderrPipe()
+ if err != nil {
+ runErr.Err = err
+ errs <- runErr
+ return
+ }
+ started = time.Now()
+ err = cmd.Start()
if err != nil {
runErr.Err = err
errs <- runErr
continue
}
if fdStderr != nil {
- tai64n.FromTime(time.Now(), ts)
+ ts.FromTime(time.Now())
LogMutex.Lock()
- fmt.Fprintf(fdStderr, "%s %s\n", ts.Encode(), line)
+ fmt.Fprintln(fdStderr, tai64n.Encode(ts[:]), line)
LogMutex.Unlock()
}
if StderrSilent {
}
}
- // Commit .dep
+ // Commit .rec
if !NoSync {
err = fdDep.Sync()
if err != nil {