You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

64 lines
1.6 KiB

  1. package cli
  2. import (
  3. "bytes"
  4. "io"
  5. "os"
  6. )
  7. // RunWithArgs executes the given command with the specified command line args
  8. // and environmental variables set. It returns any error returned from cmd.Execute()
  9. func RunWithArgs(cmd Executable, args []string, env map[string]string) error {
  10. oargs := os.Args
  11. oenv := map[string]string{}
  12. // defer returns the environment back to normal
  13. defer func() {
  14. os.Args = oargs
  15. for k, v := range oenv {
  16. os.Setenv(k, v)
  17. }
  18. }()
  19. // set the args and env how we want them
  20. os.Args = args
  21. for k, v := range env {
  22. // backup old value if there, to restore at end
  23. oenv[k] = os.Getenv(k)
  24. err := os.Setenv(k, v)
  25. if err != nil {
  26. return err
  27. }
  28. }
  29. // and finally run the command
  30. return cmd.Execute()
  31. }
  32. // RunCaptureWithArgs executes the given command with the specified command line args
  33. // and environmental variables set. It returns whatever was writen to
  34. // stdout along with any error returned from cmd.Execute()
  35. func RunCaptureWithArgs(cmd Executable, args []string, env map[string]string) (output string, err error) {
  36. old := os.Stdout // keep backup of the real stdout
  37. r, w, _ := os.Pipe()
  38. os.Stdout = w
  39. defer func() {
  40. os.Stdout = old // restoring the real stdout
  41. }()
  42. outC := make(chan string)
  43. // copy the output in a separate goroutine so printing can't block indefinitely
  44. go func() {
  45. var buf bytes.Buffer
  46. // io.Copy will end when we call w.Close() below
  47. io.Copy(&buf, r)
  48. outC <- buf.String()
  49. }()
  50. // now run the command
  51. err = RunWithArgs(cmd, args, env)
  52. // and grab the stdout to return
  53. w.Close()
  54. output = <-outC
  55. return output, err
  56. }