@@ -3,6 +3,7 @@ package registries
33import (
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