...

Source file src/oss.terrastruct.com/util-go/xmain/stdlib_exec.go

Documentation: oss.terrastruct.com/util-go/xmain

     1  package xmain
     2  
     3  import (
     4  	"bytes"
     5  	"strconv"
     6  )
     7  
     8  // Code here was copied from src/os/exec/exec.go.
     9  
    10  // prefixSuffixSaver is an io.Writer which retains the first N bytes
    11  // and the last N bytes written to it. The Bytes() methods reconstructs
    12  // it with a pretty error message.
    13  type prefixSuffixSaver struct {
    14  	N         int // max size of prefix or suffix
    15  	prefix    []byte
    16  	suffix    []byte // ring buffer once len(suffix) == N
    17  	suffixOff int    // offset to write into suffix
    18  	skipped   int64
    19  }
    20  
    21  func (w *prefixSuffixSaver) Write(p []byte) (n int, err error) {
    22  	lenp := len(p)
    23  	p = w.fill(&w.prefix, p)
    24  
    25  	// Only keep the last w.N bytes of suffix data.
    26  	if overage := len(p) - w.N; overage > 0 {
    27  		p = p[overage:]
    28  		w.skipped += int64(overage)
    29  	}
    30  	p = w.fill(&w.suffix, p)
    31  
    32  	// w.suffix is full now if p is non-empty. Overwrite it in a circle.
    33  	for len(p) > 0 { // 0, 1, or 2 iterations.
    34  		n := copy(w.suffix[w.suffixOff:], p)
    35  		p = p[n:]
    36  		w.skipped += int64(n)
    37  		w.suffixOff += n
    38  		if w.suffixOff == w.N {
    39  			w.suffixOff = 0
    40  		}
    41  	}
    42  	return lenp, nil
    43  }
    44  
    45  // fill appends up to len(p) bytes of p to *dst, such that *dst does not
    46  // grow larger than w.N. It returns the un-appended suffix of p.
    47  func (w *prefixSuffixSaver) fill(dst *[]byte, p []byte) (pRemain []byte) {
    48  	if remain := w.N - len(*dst); remain > 0 {
    49  		add := minInt(len(p), remain)
    50  		*dst = append(*dst, p[:add]...)
    51  		p = p[add:]
    52  	}
    53  	return p
    54  }
    55  
    56  func (w *prefixSuffixSaver) Bytes() []byte {
    57  	if w.suffix == nil {
    58  		return w.prefix
    59  	}
    60  	if w.skipped == 0 {
    61  		return append(w.prefix, w.suffix...)
    62  	}
    63  	var buf bytes.Buffer
    64  	buf.Grow(len(w.prefix) + len(w.suffix) + 50)
    65  	buf.Write(w.prefix)
    66  	buf.WriteString("\n... omitting ")
    67  	buf.WriteString(strconv.FormatInt(w.skipped, 10))
    68  	buf.WriteString(" bytes ...\n")
    69  	buf.Write(w.suffix[w.suffixOff:])
    70  	buf.Write(w.suffix[:w.suffixOff])
    71  	return buf.Bytes()
    72  }
    73  
    74  func minInt(a, b int) int {
    75  	if a < b {
    76  		return a
    77  	}
    78  	return b
    79  }
    80  

View as plain text