blob: 834c3d25e8e0cb3ad92994c850c0696804b797cc [file] [log] [blame]
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package fix
import (
"bytes"
"fmt"
"os"
"os/exec"
"strings"
)
func udiff(x, y []byte) ([]byte, error) {
if bytes.Equal(x, y) {
return nil, nil
}
xp, err := pipe(x)
if err != nil {
return nil, err
}
defer xp.Close()
yp, err := pipe(y)
if err != nil {
return nil, err
}
defer yp.Close()
var stderr bytes.Buffer
cmd := exec.Command("diff", "-u", "/dev/fd/3", "/dev/fd/4")
cmd.ExtraFiles = []*os.File{xp, yp}
cmd.Stderr = &stderr
stdout, err := cmd.Output()
if ee, ok := err.(*exec.ExitError); ok {
if exitErrorMeansDiff(ee) {
err = nil
}
}
if err != nil {
return nil, err
}
if stderr.Len() != 0 {
return nil, fmt.Errorf("diff: %s", &stderr)
}
nl := []byte("\n")
lines := bytes.Split(stdout, nl)
if len(lines) < 2 {
return stdout, nil
}
if strings.HasPrefix(string(lines[0]), "--- /dev/fd/3\t") &&
strings.HasPrefix(string(lines[1]), "+++ /dev/fd/4\t") {
stdout = bytes.Join(lines[2:], nl)
}
return stdout, nil
}
func pipe(data []byte) (*os.File, error) {
pr, pw, err := os.Pipe()
if err != nil {
return nil, fmt.Errorf("os.Pipe: %v", err)
}
go func() {
pw.Write(data)
pw.Close()
}()
return pr, nil
}