github.com/vugu/vugu@v0.3.6-0.20240430171613-3f6f402e014b/vugufmt/diff.go (about) 1 // Copyright 2009 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 // This file is a modification of https://golang.org/src/cmd/gofmt/gofmt.go 6 7 package vugufmt 8 9 import ( 10 "bytes" 11 "fmt" 12 "os" 13 "os/exec" 14 "path/filepath" 15 "runtime" 16 ) 17 18 func writeTempFile(dir, prefix string, data []byte) (string, error) { 19 file, err := os.CreateTemp(dir, prefix) 20 if err != nil { 21 return "", err 22 } 23 _, err = file.Write(data) 24 if err1 := file.Close(); err == nil { 25 err = err1 26 } 27 if err != nil { 28 os.Remove(file.Name()) 29 return "", err 30 } 31 return file.Name(), nil 32 } 33 34 func diff(b1, b2 []byte, filename string) (data []byte, err error) { 35 f1, err := writeTempFile("", "vugufmt", b1) 36 if err != nil { 37 return 38 } 39 defer os.Remove(f1) 40 f2, err := writeTempFile("", "vugufmt", b2) 41 if err != nil { 42 return 43 } 44 defer os.Remove(f2) 45 cmd := "diff" 46 if runtime.GOOS == "plan9" { 47 cmd = "/bin/ape/diff" 48 } 49 data, err = exec.Command(cmd, "-u", f1, f2).CombinedOutput() 50 if len(data) > 0 { 51 // diff exits with a non-zero status when the files don't match. 52 // Ignore that failure as long as we get output. 53 return replaceTempFilename(data, filename) 54 } 55 return 56 } 57 58 // replaceTempFilename replaces temporary filenames in diff with actual one. 59 func replaceTempFilename(diff []byte, filename string) ([]byte, error) { 60 61 bs := bytes.SplitN(diff, []byte{'\n'}, 3) 62 63 if len(bs) < 3 { 64 return nil, fmt.Errorf("got unexpected diff for %s", filename) 65 } 66 67 // Preserve timestamps. 68 var t0, t1 []byte 69 70 if i := bytes.LastIndexByte(bs[0], '\t'); i != -1 { 71 t0 = bs[0][i:] 72 } 73 74 if i := bytes.LastIndexByte(bs[1], '\t'); i != -1 { 75 t1 = bs[1][i:] 76 } 77 78 // Always print filepath with slash separator. 79 f := filepath.ToSlash(filename) 80 bs[0] = []byte(fmt.Sprintf("--- %s%s", f+".orig", t0)) 81 bs[1] = []byte(fmt.Sprintf("+++ %s%s", f, t1)) 82 return bytes.Join(bs, []byte{'\n'}), nil 83 }