File: cmd.go

package info (click to toggle)
golang-github-aws-aws-sdk-go-v2 1.17.1-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 384,244 kB
  • sloc: java: 13,538; makefile: 400; sh: 137
file content (96 lines) | stat: -rw-r--r-- 1,929 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package main

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"os"
	"os/exec"
	"runtime"
)

// Work provides a pending job to be done.
type Work struct {
	Path string
	Cmd  string
}

// WorkLog provides the result of a job.
type WorkLog struct {
	Path, Cmd string
	Err       error
	Output    io.Reader
}

// CommandWorker provides a consumer of work jobs and posts results to the
// worklog.
func CommandWorker(ctx context.Context, jobs <-chan Work, results chan<- WorkLog, streamOut io.Writer) {
	for {
		var result WorkLog

		select {
		case <-ctx.Done():
			return
		case w, ok := <-jobs:
			if !ok {
				return
			}

			outBuffer := bytes.NewBuffer(nil)
			outWriter := io.Writer(outBuffer)

			if streamOut != nil {
				outWriter = io.MultiWriter(outWriter, streamOut)
			}

			result.Path = w.Path
			result.Cmd = w.Cmd

			cmd, err := NewCommand(ctx, outWriter, outWriter, w.Path, w.Cmd)
			if err != nil {
				result.Err = fmt.Errorf("failed to build command, %w", err)
				break
			}

			if err := cmd.Run(); err != nil {
				result.Err = fmt.Errorf("failed to run command, %v", err)
			}

			if streamOut == nil {
				outReader := bytes.NewReader(outBuffer.Bytes())
				result.Output = outReader
			}
		}

		select {
		case <-ctx.Done():
			return
		case results <- result:
		}
	}
}

// NewCommand initializes and returns a exec.Cmd for the command provided.
func NewCommand(ctx context.Context, stdout, stderr io.Writer, workingDir string, args ...string) (*exec.Cmd, error) {
	var cmdArgs []string
	if runtime.GOOS == "windows" {
		cmdArgs = []string{"cmd.exe", "/C"}
	} else {
		cmdArgs = []string{"sh", "-c"}
	}

	if len(args) == 0 {
		return nil, fmt.Errorf("failed to create command, no arguments provided")
	}

	cmdArgs = append(cmdArgs, args...)
	cmd := exec.CommandContext(ctx, cmdArgs[0], cmdArgs[1:]...)
	cmd.Env = os.Environ()
	cmd.Dir = workingDir

	cmd.Stdout = stdout
	cmd.Stderr = stderr

	return cmd, nil
}