github.com/khulnasoft/codebase@v0.0.0-20231214144635-a707781cbb24/project/cmdbuilder.go (about)

     1  package project
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"os"
     7  	"os/exec"
     8  	"runtime"
     9  )
    10  
    11  var (
    12  	defaultTeeStdout io.Writer = os.Stdout
    13  	defaultTeeStderr io.Writer = os.Stderr
    14  )
    15  
    16  type cmdBuilder struct {
    17  	envs      []string
    18  	teeStdout io.Writer
    19  	teeStderr io.Writer
    20  	enableTee bool
    21  }
    22  
    23  func newCmdBuilder(envs []string, enableTee bool) *cmdBuilder {
    24  	return &cmdBuilder{
    25  		envs:      envs,
    26  		teeStdout: defaultTeeStdout,
    27  		teeStderr: defaultTeeStderr,
    28  		enableTee: enableTee,
    29  	}
    30  }
    31  
    32  func (cb *cmdBuilder) build(ctx context.Context, command string) (*exec.Cmd, io.Reader, io.Reader, error) {
    33  	shell := "sh"
    34  	args := []string{"-c", command}
    35  	if runtime.GOOS == "windows" {
    36  		// Under Windows the executable sh is not always available
    37  		// If running under MinGW the environment variable SHELL would be set
    38  		SHELL := os.Getenv("SHELL")
    39  		// Otherwise use the environment variable COMSPEC (path to cmd.exe)
    40  		COMSPEC := os.Getenv("COMSPEC")
    41  		if SHELL != "" {
    42  			shell = SHELL
    43  		} else if COMSPEC != "" {
    44  			shell = COMSPEC
    45  			// cmd.exe uses "/c" instead of "-c"
    46  			args[0] = "/c"
    47  		}
    48  	}
    49  	cmd := exec.CommandContext(ctx, shell, args...)
    50  	cmd.Env = cb.envs
    51  	stdout, err := cmd.StdoutPipe()
    52  	if err != nil {
    53  		return nil, nil, nil, err
    54  	}
    55  	stderr, err := cmd.StderrPipe()
    56  	if err != nil {
    57  		return nil, nil, nil, err
    58  	}
    59  	var (
    60  		teeOut io.Reader = stdout
    61  		teeErr io.Reader = stderr
    62  	)
    63  	if cb.enableTee {
    64  		teeOut = io.TeeReader(stdout, cb.teeStdout)
    65  		teeErr = io.TeeReader(stderr, cb.teeStderr)
    66  	}
    67  	return cmd, teeOut, teeErr, nil
    68  }