Files

163 lines
3.9 KiB
Go
Raw Permalink Normal View History

2018-12-16 18:28:18 +11:00
package cmd
import (
2018-12-16 20:16:40 +11:00
"bytes"
2019-01-08 07:58:46 +11:00
"fmt"
2020-02-23 06:03:00 +11:00
"os"
2018-12-16 18:28:18 +11:00
"os/exec"
"path/filepath"
2019-01-08 07:58:46 +11:00
"strings"
2018-12-19 12:49:21 -08:00
"syscall"
2018-12-16 18:28:18 +11:00
)
// ProgramHelper - Utility functions around installed applications
2019-01-08 07:58:46 +11:00
type ProgramHelper struct {
2020-02-23 06:03:00 +11:00
shell *ShellHelper
verbose bool
2019-01-08 07:58:46 +11:00
}
2018-12-16 18:28:18 +11:00
// NewProgramHelper - Creates a new ProgramHelper
2020-02-23 06:03:00 +11:00
func NewProgramHelper(verbose ...bool) *ProgramHelper {
result := &ProgramHelper{
2019-01-08 07:58:46 +11:00
shell: NewShellHelper(),
}
2020-02-23 06:03:00 +11:00
if len(verbose) > 0 {
result.verbose = verbose[0]
if result.verbose {
result.shell.SetVerbose()
}
}
return result
2018-12-16 18:28:18 +11:00
}
// IsInstalled tries to determine if the given binary name is installed
func (p *ProgramHelper) IsInstalled(programName string) bool {
_, err := exec.LookPath(programName)
return err == nil
}
// Program - A struct to define an installed application/binary
type Program struct {
2020-02-23 06:03:00 +11:00
Name string `json:"name"`
Path string `json:"path"`
verbose bool
2018-12-16 18:28:18 +11:00
}
// FindProgram attempts to find the given program on the system.FindProgram
// Returns a struct with the name and path to the program
func (p *ProgramHelper) FindProgram(programName string) *Program {
path, err := exec.LookPath(programName)
if err != nil {
return nil
}
path, err = filepath.Abs(path)
if err != nil {
return nil
}
return &Program{
2020-02-23 06:03:00 +11:00
Name: programName,
Path: path,
verbose: p.verbose,
2018-12-16 18:28:18 +11:00
}
}
2018-12-16 20:16:40 +11:00
2018-12-23 15:37:51 +11:00
// GetFullPathToBinary returns the full path the the current binary
2018-12-16 20:16:40 +11:00
func (p *Program) GetFullPathToBinary() (string, error) {
2018-12-19 12:49:21 -08:00
return filepath.Abs(p.Path)
2018-12-16 20:16:40 +11:00
}
// Run will execute the program with the given parameters
2019-04-10 08:38:46 +10:00
// Returns stdout + stderr as strings and an error if one occurred
2018-12-23 15:37:51 +11:00
func (p *Program) Run(vars ...string) (stdout, stderr string, exitCode int, err error) {
2018-12-16 20:16:40 +11:00
command, err := p.GetFullPathToBinary()
if err != nil {
2018-12-23 15:37:51 +11:00
return "", "", 1, err
2018-12-16 20:16:40 +11:00
}
cmd := exec.Command(command, vars...)
2020-02-23 06:03:00 +11:00
if !p.verbose {
var stdo, stde bytes.Buffer
cmd.Stdout = &stdo
cmd.Stderr = &stde
err = cmd.Run()
stdout = string(stdo.Bytes())
stderr = string(stde.Bytes())
} else {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
}
2018-12-19 12:49:21 -08:00
// https://stackoverflow.com/questions/10385551/get-exit-code-go
if err != nil {
// try to get the exit code
if exitError, ok := err.(*exec.ExitError); ok {
ws := exitError.Sys().(syscall.WaitStatus)
exitCode = ws.ExitStatus()
} else {
exitCode = 1
if stderr == "" {
stderr = err.Error()
}
}
} else {
// success, exitCode should be 0 if go is ok
ws := cmd.ProcessState.Sys().(syscall.WaitStatus)
exitCode = ws.ExitStatus()
}
2018-12-16 20:16:40 +11:00
return
}
2019-01-08 07:58:46 +11:00
// InstallGoPackage installs the given Go package
func (p *ProgramHelper) InstallGoPackage(packageName string) error {
2019-05-09 13:58:49 +10:00
args := strings.Split("get "+packageName, " ")
2019-01-08 07:58:46 +11:00
_, stderr, err := p.shell.Run("go", args...)
if err != nil {
fmt.Println(stderr)
}
return err
}
2019-11-05 14:47:05 +11:00
// InstallNPMPackage installs the given npm package
func (p *ProgramHelper) InstallNPMPackage(packageName string, save bool) error {
args := strings.Split("install "+packageName, " ")
if save {
args = append(args, "--save")
}
_, stderr, err := p.shell.Run("npm", args...)
if err != nil {
fmt.Println(stderr)
}
return err
}
2019-01-08 07:58:46 +11:00
// RunCommand runs the given command
func (p *ProgramHelper) RunCommand(command string) error {
args := strings.Split(command, " ")
2019-01-10 22:48:54 +11:00
return p.RunCommandArray(args)
}
// RunCommandArray runs the command specified in the array
2019-05-07 08:48:52 +10:00
func (p *ProgramHelper) RunCommandArray(args []string, dir ...string) error {
programCommand := args[0]
2019-01-08 07:58:46 +11:00
// TODO: Run FindProgram here and get the full path to the exe
program, err := exec.LookPath(programCommand)
2019-01-08 07:58:46 +11:00
if err != nil {
fmt.Printf("ERROR: Looks like '%s' isn't installed. Please install and try again.", programCommand)
2019-01-08 07:58:46 +11:00
return err
}
2019-11-05 14:47:05 +11:00
2019-01-08 07:58:46 +11:00
args = args[1:]
2019-05-07 08:48:52 +10:00
var stderr string
2019-10-08 06:12:08 +11:00
var stdout string
2019-05-07 08:48:52 +10:00
if len(dir) > 0 {
2019-10-08 06:12:08 +11:00
stdout, stderr, err = p.shell.RunInDirectory(dir[0], program, args...)
2019-05-07 08:48:52 +10:00
} else {
2019-10-08 06:12:08 +11:00
stdout, stderr, err = p.shell.Run(program, args...)
2019-05-07 08:48:52 +10:00
}
2019-01-08 07:58:46 +11:00
if err != nil {
fmt.Println(stderr)
2019-10-08 06:12:08 +11:00
fmt.Println(stdout)
2019-01-08 07:58:46 +11:00
}
return err
}