-
Notifications
You must be signed in to change notification settings - Fork 34
Expand file tree
/
Copy pathshell.go
More file actions
94 lines (84 loc) · 2.43 KB
/
shell.go
File metadata and controls
94 lines (84 loc) · 2.43 KB
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
// Copyright 2022-2025 Salesforce, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package hooks
import (
"fmt"
"io"
"os"
"os/exec"
"runtime"
"strings"
)
// ExecInterface is an interface for running shell commands in the OS
type ExecInterface interface {
Command(env []string, stdout io.Writer, stderr io.Writer, stdin io.Reader, name string, arg ...string) ShellCommand
}
type ShellCommand interface {
Run() error
CombinedOutput() ([]byte, error)
StdoutPipe() (io.ReadCloser, error)
StderrPipe() (io.ReadCloser, error)
Start() error
Wait() error
GetProcess() *os.Process
}
type ShellExec struct{}
// command sets arguments for the shell supported by the current operating system
func (ShellExec) command(name string, arg ...string) *exec.Cmd {
script := fmt.Sprintf("%s %s", name, strings.Join(arg, " "))
switch {
case runtime.GOOS == "windows":
return exec.Command("powershell", "-Command", script)
case os.Getenv("SHELL") != "":
return exec.Command(os.Getenv("SHELL"), "-c", script)
default:
return exec.Command("sh", "-c", script)
}
}
// Command creates a command ready to be run with the current processes shell
func (sh ShellExec) Command(env []string, stdout io.Writer, stderr io.Writer, stdin io.Reader, name string, arg ...string) ShellCommand {
cmd := sh.command(name, arg...)
cmd.Env = env
if stdout != nil {
cmd.Stdout = stdout
}
if stderr != nil {
cmd.Stderr = stderr
}
if stdin != nil {
cmd.Stdin = stdin
}
return execCommander{cmd}
}
// execCommander wraps the command value from the exec package
type execCommander struct {
*exec.Cmd
}
// GetProcess returns the underlying process
func (e execCommander) GetProcess() *os.Process {
if e.Cmd != nil {
return e.Process
}
return nil
}
type HookExecOpts struct {
Directory string
Hook HookScript
Args map[string]string
Env map[string]string
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
Exec ExecInterface
}