npm/util/ioutil/grep.go (77 lines of code) (raw):
// technically should have a build constraint for !windows, but iptm.go imports this, and there is no build constraint for iptm.go
package ioutil
import (
"fmt"
utilexec "k8s.io/utils/exec"
)
// Grep is the grep command string
const (
Grep = "grep"
GrepRegexFlag = "-P"
GrepOnlyMatchingFlag = "-o"
GrepAntiMatchFlag = "-v"
GrepQuietFlag = "-q"
GrepBeforeFlag = "-B"
)
func DoublePipeToGrep(command, grepCommand1, grepCommand2 utilexec.Cmd) (searchResults []byte, gotMatches bool, commandError error) {
pipe, commandError := command.StdoutPipe()
if commandError != nil {
return
}
grepCommand1.SetStdin(pipe)
grepPipe, commandError := grepCommand1.StdoutPipe()
if commandError != nil {
_ = pipe.Close()
commandError = fmt.Errorf("error getting pipe for grep command: %w", commandError)
return
}
grepCommand2.SetStdin(grepPipe)
closePipes := func() {
_ = grepPipe.Close()
_ = pipe.Close()
}
defer closePipes()
commandError = grepCommand1.Start()
if commandError != nil {
commandError = fmt.Errorf("error while starting first grep command: %w", commandError)
return
}
commandError = command.Start()
if commandError != nil {
commandError = fmt.Errorf("error while starting command: %w", commandError)
_ = grepCommand1.Wait()
return
}
waitForAll := func() {
_ = command.Wait()
_ = grepCommand1.Wait()
}
defer waitForAll()
output, err := grepCommand2.CombinedOutput()
if err != nil {
// grep returns err status 1 if nothing is found
return
}
searchResults = output
gotMatches = true
return searchResults, gotMatches, commandError // include named results to appease lint
}
func PipeCommandToGrep(command, grepCommand utilexec.Cmd) (searchResults []byte, gotMatches bool, commandError error) {
pipe, commandError := command.StdoutPipe()
if commandError != nil {
return
}
closePipe := func() { _ = pipe.Close() } // appease go lint
defer closePipe()
grepCommand.SetStdin(pipe)
commandError = command.Start()
if commandError != nil {
return
}
// Without this wait, defunct iptable child process are created
wait := func() { _ = command.Wait() } // appease go lint
defer wait()
output, err := grepCommand.CombinedOutput()
if err != nil {
// grep returns err status 1 if nothing is found
// but the other command's exit status gets propagated through this CombinedOutput, so we might have errors undetected
return
}
searchResults = output
gotMatches = true
return
}