Advertisement
aexvir

magefile run helper

Oct 21st, 2022
1,382
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 3.09 KB | None | 0 0
  1. // fancy-ish log of a task step
  2. func logstep(text string) {
  3.     fmt.Println(
  4.         color.MagentaString(">"),
  5.         color.New(color.Bold).Sprint(text),
  6.     )
  7. }
  8.  
  9. // command runner holds the metadata for a specific command
  10. type runner struct {
  11.     cmd      *exec.Cmd
  12.     program  string
  13.     args     []string
  14.     okmsg    string
  15.     errmsg   string
  16.     quiet    bool
  17.     allowerr bool
  18. }
  19.  
  20. // exec a command returning its error and pretty printing the ok and error messages
  21. func (r *runner) exec() error {
  22.     if !r.quiet {
  23.         logstep(fmt.Sprint(r.program, " ", strings.Join(r.args, " ")))
  24.     }
  25.  
  26.     err := r.cmd.Run()
  27.  
  28.     if !r.allowerr && err != nil {
  29.         if !r.quiet && r.errmsg != "" {
  30.             color.Red(r.errmsg)
  31.         }
  32.         return err
  33.     }
  34.  
  35.     if !r.quiet && r.okmsg != "" {
  36.         color.Green(r.okmsg)
  37.     }
  38.     return nil
  39. }
  40.  
  41. // build a command runner for a specific program
  42. func cmd(ctx context.Context, program string, opts ...runneropt) (*runner, error) {
  43.     command := exec.CommandContext(ctx, program)
  44.     command.Stdout = os.Stdout
  45.     command.Stderr = os.Stderr
  46.  
  47.     r := runner{
  48.         cmd:     command,
  49.         program: program,
  50.     }
  51.  
  52.     for _, opt := range opts {
  53.         err := opt(&r)
  54.         if err != nil {
  55.             return nil, err
  56.         }
  57.     }
  58.  
  59.     command.Args = append([]string{program}, r.args...)
  60.  
  61.     return &r, nil
  62. }
  63.  
  64. // helper function to avoid repetition while gracefully handling errors
  65. func run(ctx context.Context, program string, opts ...runneropt) error {
  66.     rnr, err := cmd(ctx, program, opts...)
  67.     if err != nil {
  68.         return err
  69.     }
  70.  
  71.     return rnr.exec()
  72. }
  73.  
  74. // options to customize the behaviour of the command runner
  75. type runneropt func(r *runner) error
  76.  
  77. // sets up environment variables for the command
  78. func withenv(vars ...string) runneropt {
  79.     return func(r *runner) error {
  80.         r.cmd.Env = os.Environ()[:]
  81.         for _, vrb := range vars {
  82.             items := strings.Split(vrb, "=")
  83.             if len(items) != 2 {
  84.                 return errors.New("")
  85.             }
  86.             r.cmd.Env = append(r.cmd.Env, vrb)
  87.         }
  88.         return nil
  89.     }
  90. }
  91.  
  92. // command arguments
  93. func withargs(args ...string) runneropt {
  94.     return func(r *runner) error {
  95.         r.args = args
  96.         return nil
  97.     }
  98. }
  99.  
  100. // sets a message to be printed when the command finishes successfully
  101. func withokmsg(msg string) runneropt {
  102.     return func(r *runner) error {
  103.         r.okmsg = msg
  104.         return nil
  105.     }
  106. }
  107.  
  108. // sets a message to be printed when the command fails
  109. func witherrmsg(msg string) runneropt {
  110.     return func(r *runner) error {
  111.         r.errmsg = msg
  112.         return nil
  113.     }
  114. }
  115.  
  116. // sets the directory where the command should be run inside
  117. func withdir(dir string) runneropt {
  118.     return func(r *runner) error {
  119.         r.cmd.Dir = dir
  120.         return nil
  121.     }
  122. }
  123.  
  124. // silences all output for the command; useful when handling that on the caller side
  125. func withoutnoise() runneropt {
  126.     return func(r *runner) error {
  127.         r.quiet = true
  128.         r.cmd.Stdout = nil
  129.         r.cmd.Stderr = nil
  130.  
  131.         return nil
  132.     }
  133. }
  134.  
  135. // set up stdout writer
  136. func withstdout(w io.Writer) runneropt {
  137.     return func(r *runner) error {
  138.         r.cmd.Stdout = w
  139.         return nil
  140.     }
  141. }
  142.  
  143. // allow errors in the command
  144. func withallowerr() runneropt {
  145.     return func(r *runner) error {
  146.         r.allowerr = true
  147.         return nil
  148.     }
  149. }
  150.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement