func runXcodeBuildCmd(useStdOut bool, args ...string) (string, int, error) { // command buildCmd := cmd.CreateXcodebuildCmd(args...) // output buffer var outBuffer bytes.Buffer // additional output writers, like StdOut outWritters := []io.Writer{} if useStdOut { outWritters = append(outWritters, os.Stdout) } // unify as a single writer outWritter := cmd.CreateBufferedWriter(&outBuffer, outWritters...) // and set the writer buildCmd.Stdin = nil buildCmd.Stdout = outWritter buildCmd.Stderr = outWritter buildCmd.Env = append(os.Environ(), xcodeCommandEnvs...) cmdArgsForPrint := cmd.PrintableCommandArgsWithEnvs(buildCmd.Args, xcodeCommandEnvs) log.Detail("$ %s", cmdArgsForPrint) err := buildCmd.Run() if err != nil { if exitError, ok := err.(*exec.ExitError); ok { waitStatus, ok := exitError.Sys().(syscall.WaitStatus) if !ok { return outBuffer.String(), 1, errors.New("Failed to cast exit status") } return outBuffer.String(), waitStatus.ExitStatus(), err } return outBuffer.String(), 1, err } return outBuffer.String(), 0, nil }
func runPrettyXcodeBuildCmd(useStdOut bool, xcprettyArgs []string, xcodebuildArgs []string) (string, int, error) { // buildCmd := cmd.CreateXcodebuildCmd(xcodebuildArgs...) prettyCmd := cmd.CreateXcprettyCmd(xcprettyArgs...) // var buildOutBuffer bytes.Buffer // pipeReader, pipeWriter := io.Pipe() // // build outputs: // - write it into a buffer // - write it into the pipe, which will be fed into xcpretty buildOutWriters := []io.Writer{pipeWriter} buildOutWriter := cmd.CreateBufferedWriter(&buildOutBuffer, buildOutWriters...) // var prettyOutWriter io.Writer if useStdOut { prettyOutWriter = os.Stdout } // and set the writers buildCmd.Stdin = nil buildCmd.Stdout = buildOutWriter buildCmd.Stderr = buildOutWriter // prettyCmd.Stdin = pipeReader prettyCmd.Stdout = prettyOutWriter prettyCmd.Stderr = prettyOutWriter // buildCmd.Env = append(os.Environ(), xcodeCommandEnvs...) log.Detail("$ set -o pipefail && %s | %v", cmd.PrintableCommandArgsWithEnvs(buildCmd.Args, xcodeCommandEnvs), cmd.PrintableCommandArgs(prettyCmd.Args)) fmt.Println() if err := buildCmd.Start(); err != nil { return buildOutBuffer.String(), 1, err } if err := prettyCmd.Start(); err != nil { return buildOutBuffer.String(), 1, err } defer func() { if err := pipeWriter.Close(); err != nil { log.Warn("Failed to close xcodebuild-xcpretty pipe, error: %s", err) } if err := prettyCmd.Wait(); err != nil { log.Warn("xcpretty command failed, error: %s", err) } }() if err := buildCmd.Wait(); err != nil { if exitError, ok := err.(*exec.ExitError); ok { waitStatus, ok := exitError.Sys().(syscall.WaitStatus) if !ok { return buildOutBuffer.String(), 1, errors.New("Failed to cast exit status") } return buildOutBuffer.String(), waitStatus.ExitStatus(), err } return buildOutBuffer.String(), 1, err } return buildOutBuffer.String(), 0, nil }