github.com/jgbaldwinbrown/perf@v0.1.1/internal/diff/diff.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package diff 6 7 import ( 8 "fmt" 9 "os" 10 "os/exec" 11 "runtime" 12 ) 13 14 func writeTempFile(dir, prefix string, data []byte) (string, error) { 15 file, err := os.CreateTemp(dir, prefix) 16 if err != nil { 17 return "", err 18 } 19 _, err = file.Write(data) 20 if err1 := file.Close(); err == nil { 21 err = err1 22 } 23 if err != nil { 24 os.Remove(file.Name()) 25 return "", err 26 } 27 return file.Name(), nil 28 } 29 30 // Diff returns a human-readable description of the differences between s1 and s2. 31 // If the "diff" command is available, it returns the output of unified diff on s1 and s2. 32 // If the result is non-empty, the strings differ or the diff command failed. 33 func Diff(s1, s2 string) string { 34 if s1 == s2 { 35 return "" 36 } 37 if _, err := exec.LookPath("diff"); err != nil { 38 return fmt.Sprintf("diff command unavailable\nold: %q\nnew: %q", s1, s2) 39 } 40 f1, err := writeTempFile("", "benchfmt_test", []byte(s1)) 41 if err != nil { 42 return err.Error() 43 } 44 defer os.Remove(f1) 45 46 f2, err := writeTempFile("", "benchfmt_test", []byte(s2)) 47 if err != nil { 48 return err.Error() 49 } 50 defer os.Remove(f2) 51 52 cmd := "diff" 53 if runtime.GOOS == "plan9" { 54 cmd = "/bin/ape/diff" 55 } 56 57 data, err := exec.Command(cmd, "-u", f1, f2).CombinedOutput() 58 if len(data) > 0 { 59 // diff exits with a non-zero status when the files don't match. 60 // Ignore that failure as long as we get output. 61 err = nil 62 } 63 if err != nil { 64 data = append(data, []byte(err.Error())...) 65 } 66 return string(data) 67 }