1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
// The fmt command applies standard formatting to text proto files and preserves
// comments.
package main
import (
"bufio"
"bytes"
"fmt"
"io/ioutil"
"os"
"strings"
"flag"
// Google internal base/go package, commented out by copybara
log "github.com/golang/glog"
"github.com/protocolbuffers/txtpbfmt/parser"
)
var (
// Top level flags.
dryRun = flag.Bool("dry_run", false, "Enable dry run mode.")
expandAllChildren = flag.Bool("expand_all_children", false, "Expand all children irrespective of initial state.")
skipAllColons = flag.Bool("skip_all_colons", false, "Skip colons whenever possible.")
sortFieldsByFieldName = flag.Bool("sort_fields_by_field_name", false, "Sort fields by field name.")
sortRepeatedFieldsByContent = flag.Bool("sort_repeated_fields_by_content", false, "Sort adjacent scalar fields of the same field name by their contents.")
sortRepeatedFieldsBySubfield = flag.String("sort_repeated_fields_by_subfield", "", "Sort adjacent message fields of the given field name by the contents of the given subfield.")
removeDuplicateValuesForRepeatedFields = flag.Bool("remove_duplicate_values_for_repeated_fields", false, "Remove lines that have the same field name and scalar value as another.")
allowTripleQuotedStrings = flag.Bool("allow_triple_quoted_strings", false, `Allow Python-style """ or ''' delimited strings in input.`)
stdinDisplayPath = flag.String("stdin_display_path", "<stdin>", "The path to display when referring to the content read from stdin.")
wrapStringsAtColumn = flag.Int("wrap_strings_at_column", 0, "Max columns for string field values. (0 means no wrap.)")
wrapHTMLStrings = flag.Bool("wrap_html_strings", false, "Wrap strings containing HTML tags. (Requires wrap_strings_at_column > 0.)")
wrapStringsAfterNewlines = flag.Bool("wrap_strings_after_newlines", false, "Wrap strings after newlines.")
wrapStringsWithoutWordwrap = flag.Bool("wrap_strings_without_wordwrap", false, "Wrap strings at the given column only.")
preserveAngleBrackets = flag.Bool("preserve_angle_brackets", false, "Preserve angle brackets instead of converting to curly braces.")
smartQuotes = flag.Bool("smart_quotes", false, "Use single quotes around strings that contain double but not single quotes.")
)
const stdinPlaceholderPath = "<stdin>"
func read(path string) ([]byte, error) {
if path == stdinPlaceholderPath {
return ioutil.ReadAll(bufio.NewReader(os.Stdin))
}
return ioutil.ReadFile(path)
}
func errorf(format string, args ...interface{}) {
fmt.Fprintf(os.Stderr, format+"\n", args...)
}
func contentForLogging(content []byte) string {
res := string(content)
if len(res) > 100 {
res = res[:100] + " ... <snip> ..."
}
return res
}
func main() {
flag.Parse()
paths := flag.Args()
if len(paths) == 0 {
paths = append(paths, stdinPlaceholderPath)
}
log.Info("paths: ", paths)
errs := 0
for _, path := range paths {
if strings.HasPrefix(path, "//depot/google3/") {
path = strings.Replace(path, "//depot/google3/", "", 1)
}
displayPath := path
if path == stdinPlaceholderPath {
displayPath = *stdinDisplayPath
log.Info("path ", path, " displayed as ", displayPath)
} else {
log.Info("path ", path)
}
content, err := read(path)
if os.IsNotExist(err) {
log.Error("Ignoring path: ", err)
errs++
continue
} else if err != nil {
log.Exit(err)
}
// Only pass the verbose logger if its level is enabled.
var logger parser.Logger
if l := log.V(2); l {
logger = l
}
newContent, err := parser.FormatWithConfig(content, parser.Config{
ExpandAllChildren: *expandAllChildren,
SkipAllColons: *skipAllColons,
SortFieldsByFieldName: *sortFieldsByFieldName,
SortRepeatedFieldsByContent: *sortRepeatedFieldsByContent,
SortRepeatedFieldsBySubfield: strings.Split(*sortRepeatedFieldsBySubfield, ","),
RemoveDuplicateValuesForRepeatedFields: *removeDuplicateValuesForRepeatedFields,
AllowTripleQuotedStrings: *allowTripleQuotedStrings,
WrapStringsAtColumn: *wrapStringsAtColumn,
WrapHTMLStrings: *wrapHTMLStrings,
WrapStringsAfterNewlines: *wrapStringsAfterNewlines,
WrapStringsWithoutWordwrap: *wrapStringsWithoutWordwrap,
PreserveAngleBrackets: *preserveAngleBrackets,
SmartQuotes: *smartQuotes,
Logger: logger,
})
if err != nil {
errorf("parser.Format for path %v with content %q returned err %v", displayPath, contentForLogging(content), err)
errs++
continue
}
log.V(2).Infof("New content for path %s: %q", displayPath, newContent)
if path == stdinPlaceholderPath {
fmt.Print(string(newContent))
continue
}
if bytes.Equal(content, newContent) {
log.Info("No change for path ", displayPath)
continue
}
if *dryRun {
fmt.Println(string(newContent))
continue
}
if err := ioutil.WriteFile(path, newContent, 0664); err != nil {
log.Exit(err)
}
}
if errs > 0 {
log.Exit(errs, " error(s) encountered during execution")
}
}
|