github.com/chainguard-dev/yam@v0.0.7/pkg/yam/diff.go (about)

     1  package yam
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"os"
     7  	"os/exec"
     8  )
     9  
    10  type DiffHandler func(want, got []byte) error
    11  
    12  func ExecDiff(want, got []byte) error {
    13  	handlerOutput := os.Stderr
    14  
    15  	tempWant, err := os.CreateTemp("", "want-*")
    16  	if err != nil {
    17  		return err
    18  	}
    19  	defer os.Remove(tempWant.Name())
    20  
    21  	tempGot, err := os.CreateTemp("", "got-*")
    22  	if err != nil {
    23  		return err
    24  	}
    25  	defer os.Remove(tempGot.Name())
    26  
    27  	_, err = tempWant.Write(want)
    28  	if err != nil {
    29  		return err
    30  	}
    31  
    32  	_, err = tempGot.Write(got)
    33  	if err != nil {
    34  		return err
    35  	}
    36  
    37  	const command = "diff"
    38  	_, err = exec.LookPath(command)
    39  	if err != nil {
    40  		return fmt.Errorf("unable to execute diff command: %w", err)
    41  	}
    42  
    43  	cmd := exec.Command(
    44  		command,
    45  		"-U",
    46  		"5",
    47  		"--label",
    48  		"want",
    49  		"--label",
    50  		"got",
    51  		tempWant.Name(),
    52  		tempGot.Name(),
    53  	)
    54  	cmd.Stdout = handlerOutput
    55  	cmd.Stderr = handlerOutput
    56  
    57  	err = cmd.Run()
    58  	if err != nil {
    59  		var exitError *exec.ExitError
    60  		if errors.As(err, &exitError) {
    61  			if exitError.ExitCode() == 1 {
    62  				// that's expected for `diff` when there's a diff!
    63  
    64  				fmt.Fprint(handlerOutput, "\n") // for gap between diffs; useful if diffing multiple files.
    65  
    66  				return nil
    67  			}
    68  		}
    69  
    70  		return fmt.Errorf("error executing diff command %q: %w", cmd, err)
    71  	}
    72  
    73  	return nil
    74  }