Don't make PipelineError when only one command in a pipeline errs.

This commit is contained in:
Qi Xiao 2017-01-29 17:56:13 +00:00
parent ddbbfb9d33
commit 9281abad90
3 changed files with 34 additions and 28 deletions

View File

@ -1101,7 +1101,7 @@ func fg(ec *EvalCtx, pids ...int) {
}
}
throwCompositeError(errors)
maybeThrow(ComposeExceptionsFromPipeline(errors))
}
func tildeAbbr(ec *EvalCtx, path string) {

View File

@ -100,8 +100,9 @@ func (cp *compiler) pipeline(n *parse.Pipeline) OpFunc {
go func() {
wg.Wait()
msg := "job " + n.SourceText() + " finished"
if !allok(errors) {
msg += ", errors = " + makeCompositeError(errors).Error()
err := ComposeExceptionsFromPipeline(errors)
if err != nil {
msg += ", errors = " + err.Error()
}
if !verdict {
msg += ", pred = false"
@ -122,27 +123,12 @@ func (cp *compiler) pipeline(n *parse.Pipeline) OpFunc {
}()
} else {
wg.Wait()
maybeThrow(makeCompositeError(errors))
maybeThrow(ComposeExceptionsFromPipeline(errors))
ec.verdict = verdict
}
}
}
func makeCompositeError(errors []*Exception) error {
if allok(errors) {
return nil
}
if len(errors) == 1 {
return errors[0]
} else {
return PipelineError{errors}
}
}
func throwCompositeError(errors []*Exception) {
maybeThrow(makeCompositeError(errors))
}
func (cp *compiler) form(n *parse.Form) OpFunc {
var saveVarsOps []LValuesOp
var assignmentOps []Op

View File

@ -105,6 +105,35 @@ func (pe PipelineError) Error() string {
return b.String()
}
// ComposeExceptionsFromPipeline takes a slice of Exception pointers and
// composes a suitable error. If all elements of the slice are either nil or OK,
// a nil is returned. If there is exactly non-nil non-OK Exception, it is
// returned. Otherwise, a PipelineError built from the slice is returned, with
// nil items turned into OK's for easier access from elvishscript.
func ComposeExceptionsFromPipeline(excs []*Exception) error {
newexcs := make([]*Exception, len(excs))
notOK, lastNotOK := 0, 0
for i, e := range excs {
if e == nil {
newexcs[i] = OK
} else {
newexcs[i] = e
if e.Cause != nil {
notOK++
lastNotOK = i
}
}
}
switch notOK {
case 0:
return nil
case 1:
return newexcs[lastNotOK]
default:
return PipelineError{newexcs}
}
}
// Flow is a special type of error used for control flows.
type Flow uint
@ -180,12 +209,3 @@ func (exit ExternalCmdExit) Error() string {
return fmt.Sprint(quotedName, " has unknown WaitStatus ", ws)
}
}
func allok(es []*Exception) bool {
for _, e := range es {
if e != nil && e.Cause != nil {
return false
}
}
return true
}