github.com/Mistwind/reviewdog@v0.0.0-20230317041057-48e69b6d9e86/diff.go (about)

     1  package reviewdog
     2  
     3  import (
     4  	"context"
     5  	"os/exec"
     6  	"sync"
     7  )
     8  
     9  var _ DiffService = &DiffString{}
    10  
    11  type DiffString struct {
    12  	b     []byte
    13  	strip int
    14  }
    15  
    16  func NewDiffString(diff string, strip int) DiffService {
    17  	return &DiffString{b: []byte(diff), strip: strip}
    18  }
    19  
    20  func (d *DiffString) Diff(_ context.Context) ([]byte, error) {
    21  	return d.b, nil
    22  }
    23  
    24  func (d *DiffString) Strip() int {
    25  	return d.strip
    26  }
    27  
    28  var _ DiffService = &DiffCmd{}
    29  
    30  type DiffCmd struct {
    31  	cmd   *exec.Cmd
    32  	strip int
    33  	out   []byte
    34  	done  bool
    35  	mu    sync.RWMutex
    36  }
    37  
    38  func NewDiffCmd(cmd *exec.Cmd, strip int) *DiffCmd {
    39  	return &DiffCmd{cmd: cmd, strip: strip}
    40  }
    41  
    42  // Diff returns diff. It caches the result and can be used more than once.
    43  func (d *DiffCmd) Diff(_ context.Context) ([]byte, error) {
    44  	d.mu.Lock()
    45  	defer d.mu.Unlock()
    46  	if d.done {
    47  		return d.out, nil
    48  	}
    49  	out, err := d.cmd.Output()
    50  	// Exit status of `git diff` is 1 if diff exists, so ignore the error if diff
    51  	// presents.
    52  	if err != nil && len(out) == 0 {
    53  		return nil, err
    54  	}
    55  	d.out = out
    56  	d.done = true
    57  	return d.out, nil
    58  }
    59  
    60  func (d *DiffCmd) Strip() int {
    61  	return d.strip
    62  }
    63  
    64  // EmptyDiff service return empty diff.
    65  type EmptyDiff struct{}
    66  
    67  func (*EmptyDiff) Diff(context.Context) ([]byte, error) {
    68  	return []byte{}, nil
    69  }
    70  
    71  func (*EmptyDiff) Strip() int { return 0 }