Files
kustomize/api/internal/git/gitrunner.go
2020-12-09 17:17:21 -08:00

66 lines
1.4 KiB
Go

// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package git
import (
"os/exec"
"time"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/types"
)
// Arbitrary, but non-infinite, timeout for running commands.
const defaultDuration = 27 * time.Second
// gitRunner runs the external git binary.
type gitRunner struct {
gitProgram string
duration time.Duration
dir filesys.ConfirmedDir
}
// newCmdRunner returns a gitRunner if it can find the binary.
// It also creats a temp directory for cloning repos.
func newCmdRunner() (*gitRunner, error) {
gitProgram, err := exec.LookPath("git")
if err != nil {
return nil, errors.Wrap(err, "no 'git' program on path")
}
dir, err := filesys.NewTmpConfirmedDir()
if err != nil {
return nil, err
}
return &gitRunner{
gitProgram: gitProgram,
duration: defaultDuration,
dir: dir,
}, nil
}
// run a command with a timeout.
func (r gitRunner) run(args ...string) (err error) {
ch := make(chan bool, 1)
defer close(ch)
//nolint: gosec
cmd := exec.Command(r.gitProgram, args...)
cmd.Dir = r.dir.String()
timer := time.NewTimer(r.duration)
defer timer.Stop()
go func() {
_, err = cmd.CombinedOutput()
ch <- true
}()
select {
case <-ch:
if err != nil {
return errors.Wrapf(err, "git cmd = '%s'", cmd.String())
}
return nil
case <-timer.C:
return types.NewErrTimeOut(r.duration, cmd.String())
}
}