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