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 }