Skip to content

Commit 59002a5

Browse files
committed
Add ProxiedCmd type
1 parent ef6059a commit 59002a5

1 file changed

Lines changed: 89 additions & 0 deletions

File tree

‎go/extractor/registries/registryproxy.go‎

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package registries
33
import (
44
"encoding/json"
55
"fmt"
6+
"io"
67
"log/slog"
78
"net/url"
89
"os"
@@ -203,3 +204,91 @@ func ApplyProxyEnvVars(cmd *exec.Cmd) {
203204
slog.String("proxy_vars", strings.Join(proxy_vars, ",")),
204205
)
205206
}
207+
208+
// Wrapper around [exec.Cmd] for commands that need proxy setup and cleanup.
209+
type ProxiedCmd struct {
210+
cmd *exec.Cmd
211+
}
212+
213+
// Constructs a new [ProxiedCmd].
214+
func Command(name string, arg ...string) *ProxiedCmd {
215+
cmd := exec.Command(name, arg...)
216+
return &ProxiedCmd{cmd}
217+
}
218+
219+
// Applies proxy-related environment variables to the command, installs a clean-up handler and runs `fn`
220+
// with the underlying command as argument.
221+
func run[R any](proxiedCmd *ProxiedCmd, fn func(cmd *exec.Cmd) R) R {
222+
// Apply registry proxy environment variables to the command.
223+
ApplyProxyEnvVars(proxiedCmd.cmd)
224+
225+
return fn(proxiedCmd.cmd)
226+
}
227+
228+
// Runs the command and waits for it to complete.
229+
func (self ProxiedCmd) Run() error {
230+
return run[error](&self, func(cmd *exec.Cmd) error { return cmd.Run() })
231+
}
232+
233+
// Runs the command and waits for it to complete. Returns a boolean indicating whether the command was successful
234+
// and logs errors if any occur.
235+
func (self ProxiedCmd) RunCmd() bool {
236+
return run[bool](&self, func(cmd *exec.Cmd) bool {
237+
cmd.Stdout = os.Stdout
238+
cmd.Stderr = os.Stderr
239+
in, _ := cmd.StdinPipe()
240+
err := cmd.Start()
241+
if err != nil {
242+
slog.Warn(fmt.Sprintf("Running %s %v failed, continuing anyway: %s\n", cmd.Path, cmd.Args, err.Error()))
243+
return false
244+
}
245+
in.Close()
246+
err = cmd.Wait()
247+
if err != nil {
248+
slog.Warn(fmt.Sprintf("Running %s %v failed, continuing anyway: %s\n", cmd.Path, cmd.Args, err.Error()))
249+
return false
250+
}
251+
252+
return true
253+
})
254+
}
255+
256+
type Output struct {
257+
data []byte
258+
err error
259+
}
260+
261+
func (self ProxiedCmd) Output() ([]byte, error) {
262+
result := run[Output](&self, func(cmd *exec.Cmd) Output {
263+
data, err := cmd.Output()
264+
return Output{data, err}
265+
})
266+
267+
return result.data, result.err
268+
}
269+
270+
// Runs the command and returns its combined standard output and standard error.
271+
func (self ProxiedCmd) CombinedOutput() ([]byte, error) {
272+
result := run[Output](&self, func(cmd *exec.Cmd) Output {
273+
data, err := cmd.CombinedOutput()
274+
return Output{data, err}
275+
})
276+
277+
return result.data, result.err
278+
}
279+
280+
func (self ProxiedCmd) AppendEnv(kvps ...string) {
281+
self.cmd.Env = append(self.cmd.Env, kvps...)
282+
}
283+
284+
func (self ProxiedCmd) SetDir(workingDir string) {
285+
self.cmd.Dir = workingDir
286+
}
287+
288+
func (self ProxiedCmd) SetStdout(writer io.Writer) {
289+
self.cmd.Stdout = writer
290+
}
291+
292+
func (self ProxiedCmd) SetStderr(writer io.Writer) {
293+
self.cmd.Stderr = writer
294+
}

0 commit comments

Comments
 (0)