github.com/paketo-buildpacks/packit@v1.3.2-0.20211206231111-86b75c657449/pexec/executable.go (about)

     1  package pexec
     2  
     3  import (
     4  	"io"
     5  	"os"
     6  	"os/exec"
     7  	"strings"
     8  )
     9  
    10  // Executable represents an executable on the $PATH.
    11  type Executable struct {
    12  	name string
    13  }
    14  
    15  // NewExecutable returns an instance of an Executable given the name of that
    16  // executable. When given simply a name, the execuable will be looked up on the
    17  // $PATH before execution. Alternatively, when given a path, the executable
    18  // will use that path to invoke the executable file directly.
    19  func NewExecutable(name string) Executable {
    20  	return Executable{
    21  		name: name,
    22  	}
    23  }
    24  
    25  // Execute invokes the executable with a set of Execution arguments.
    26  func (e Executable) Execute(execution Execution) error {
    27  	envPath := os.Getenv("PATH")
    28  
    29  	if execution.Env != nil {
    30  		var path string
    31  		for _, variable := range execution.Env {
    32  			if strings.HasPrefix(variable, "PATH=") {
    33  				path = strings.TrimPrefix(variable, "PATH=")
    34  			}
    35  		}
    36  		if path != "" {
    37  			os.Setenv("PATH", path)
    38  		}
    39  	}
    40  
    41  	executable, err := exec.LookPath(e.name)
    42  	if err != nil {
    43  		return err
    44  	}
    45  
    46  	os.Setenv("PATH", envPath)
    47  
    48  	cmd := exec.Command(executable, execution.Args...)
    49  
    50  	if execution.Dir != "" {
    51  		cmd.Dir = execution.Dir
    52  	}
    53  
    54  	if len(execution.Env) > 0 {
    55  		cmd.Env = execution.Env
    56  	}
    57  
    58  	cmd.Stdout = execution.Stdout
    59  	cmd.Stderr = execution.Stderr
    60  
    61  	return cmd.Run()
    62  }
    63  
    64  // Execution is the set of configurable options for a given execution of the
    65  // executable.
    66  type Execution struct {
    67  	// Args is a list of the arguments to be passed to the executable.
    68  	Args []string
    69  
    70  	// Dir is the path to a directory from with the executable should be invoked.
    71  	// If Dir is not set, the current working directory will be used.
    72  	Dir string
    73  
    74  	// Env is the set of environment variables that make up the environment for
    75  	// the execution. If Env is not set, the existing os.Environ value will be
    76  	// used.
    77  	Env []string
    78  
    79  	// Stdout is where the output of stdout will be written during the execution.
    80  	Stdout io.Writer
    81  
    82  	// Stderr is where the output of stderr will be written during the execution.
    83  	Stderr io.Writer
    84  }