func canonicalize(t *testing.T, filename, content string) string { f, err := bzl.Parse(filename, []byte(content)) if err != nil { t.Fatalf("bzl.Parse(%q, %q) failed with %v; want success", filename, content, err) } return string(bzl.Format(f)) }
func format(rules []*bzl.Rule) string { var f bzl.File for _, r := range rules { f.Stmt = append(f.Stmt, r.Call) } return string(bzl.Format(&f)) }
func fixFile(fname string, rules []bzl.Expr) (err error) { buildfile, err := reconcile(fname, rules) if err != nil { return err } f, err := ioutil.TempFile("", "BUILD") if err != nil { return err } defer func() { if err == nil { if merr := os.Rename(f.Name(), fname); merr != nil { err = merr } } }() defer func() { if cerr := f.Close(); cerr != nil { if err == nil { err = cerr } } }() _, err = f.Write(bzl.Format(buildfile)) return err }
// processFile processes a single file containing data. // It has been read from filename and should be written back if fixing. func processFile(filename string, data []byte) { defer func() { if err := recover(); err != nil { fmt.Fprintf(os.Stderr, "buildifier: %s: internal error: %v\n", filename, err) exitCode = 3 } }() f, err := build.Parse(filename, data) if err != nil { // Do not use buildifier: prefix on this error. // Since it is a parse error, it begins with file:line: // and we want that to be the first thing in the error. fmt.Fprintf(os.Stderr, "%v\n", err) if exitCode < 1 { exitCode = 1 } return } if *path != "" { f.Path = *path } beforeRewrite := build.Format(f) var info build.RewriteInfo build.Rewrite(f, &info) ndata := build.Format(f) switch *mode { case "check": // check mode: print names of files that need formatting. if !bytes.Equal(data, ndata) { // Print: // name # list of what changed reformat := "" if !bytes.Equal(data, beforeRewrite) { reformat = " reformat" } log := "" if len(info.Log) > 0 && *showlog { sort.Strings(info.Log) var uniq []string last := "" for _, s := range info.Log { if s != last { last = s uniq = append(uniq, s) } } log = " " + strings.Join(uniq, " ") } fmt.Printf("%s #%s %s%s\n", filename, reformat, &info, log) } return case "diff": // diff mode: run diff on old and new. if bytes.Equal(data, ndata) { return } outfile, err := writeTemp(ndata) if err != nil { fmt.Fprintf(os.Stderr, "buildifier: %v\n", err) exitCode = 3 return } infile := filename if filename == "" { // data was read from standard filename. // Write it to a temporary file so diff can read it. infile, err = writeTemp(data) if err != nil { fmt.Fprintf(os.Stderr, "buildifier: %v\n", err) exitCode = 3 return } } diff.Show(infile, outfile) case "pipe": // pipe mode - reading from stdin, writing to stdout. // ("pipe" is not from the command line; it is set above in main.) os.Stdout.Write(ndata) return case "fix": // fix mode: update files in place as needed. if bytes.Equal(data, ndata) { return } err := ioutil.WriteFile(filename, ndata, 0666) if err != nil { fmt.Fprintf(os.Stderr, "buildifier: %s\n", err) exitCode = 3 return } if *vflag { fmt.Fprintf(os.Stderr, "fixed %s\n", filename) } } }