//ExecConcurently, for each `subrepository` in the working dir, execute the command `command` with arguments `args`. // Each command is executed in non interactive mode (no access to stdin/stdout) func ExecConcurrently(x *sbr.Workspace, command string, args ...string) <-chan Execution { executions := make(chan Execution) var waiter sync.WaitGroup // to wait for all commands to return for _, sub := range x.ScanRel() { waiter.Add(1) go func(sub string) { defer waiter.Done() cmd := exec.Command(command, args...) cmd.Dir = sub out, err := cmd.CombinedOutput() if err != nil { return } rel := filepath.Join(x.Wd(), sub) // keep //head := fmt.Sprintf("\033[00;32m%s\033[00m$ %s %s\n", sub, command, strings.Join(args, " ")) //executions <- head + string(out) result := string(out) result = strings.Trim(result, git.DefaultTrimCut) executions <- Execution{Name: sub, Rel: rel, Cmd: command, Args: args, Result: result} }(sub) } go func() { waiter.Wait() close(executions) }() return executions }
//ExecSequentially, for each `subrepository` in the working dir, execute the command `command` with arguments `args`. // It passes the stdin, stdout, and stderr to the subprocess. and wait for the result, before moving to the next one. func ExecSequentially(x *sbr.Workspace, command string, args ...string) { var count int for _, sub := range x.ScanRel() { count++ rel, err := filepath.Rel(x.Wd(), sub) if err != nil { rel = sub // use absolute path } //log.Printf("%v, %v", sub, rel) fmt.Printf("\033[00;32m%s\033[00m$ %s %s\n", rel, command, strings.Join(args, " ")) cmd := exec.Command(command, args...) cmd.Dir = sub cmd.Stderr, cmd.Stdout, cmd.Stdin = os.Stderr, os.Stdout, os.Stdin if err := cmd.Run(); err != nil { fmt.Printf("Error running '%s %s':\n %s\n", command, strings.Join(args, " "), err.Error()) } } fmt.Printf("Done (\033[00;32m%v\033[00m repositories)\n", count) }