* .do's arguments are relative paths
* .do search goes up to / by default, but can be limited with either
REDO_TOP_DIR environment variable, or by having .redo/top file in it
-* executable .do is run as is
-* shebangless .do is run with /bin/sh -e[x]
* target's completion messages are written after they finish
+* executable .do is run as is, non-executable is run with /bin/sh -e[x]
+* tracing (-x) can be done only for non-executable .do
FEATURES *goredo-features*
StderrPrefix string
Jobs sync.WaitGroup
- flagTrace = flag.Bool("x", false, fmt.Sprintf("trace current target (sh -x) (set %s=1 for others too)", EnvTrace))
+ flagTrace = flag.Bool("x", false, fmt.Sprintf("trace current target (sh -x) (set %s=1 for all others)", 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))
)
var cmdName string
var args []string
if err = unix.Access(doFilePath, unix.X_OK); err == nil {
- // Ordinary executable file
cmdName = doFilePath
args = make([]string, 0, 3)
} else {
- fd, err := os.Open(doFilePath)
- if err != nil {
- cleanup()
- return TgtErr{tgtOrig, err}
- }
- buf := make([]byte, 512)
- n, err := fd.Read(buf)
- if err != nil {
- cleanup()
- return TgtErr{tgtOrig, err}
- }
- if n > 3 && string(buf[:3]) == "#!/" {
- // Shebanged
- t := string(buf[2:n])
- nlIdx := strings.Index(t, "\n")
- if nlIdx == -1 {
- cleanup()
- return TgtErr{tgtOrig, errors.New("not fully read shebang")}
- }
- args = strings.Split(t[:nlIdx], " ")
- cmdName, args = args[0], args[1:]
+ cmdName = "/bin/sh"
+ if traced {
+ args = append(args, "-ex")
} else {
- // Shell
- cmdName = "/bin/sh"
- if traced {
- args = append(args, "-ex")
- } else {
- args = append(args, "-e")
- }
+ args = append(args, "-e")
}
args = append(args, doFile)
}