File: fmt.go

package info (click to toggle)
golang-github-protocolbuffers-txtpbfmt 0.0~git20241112.20d2c9e-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 576 kB
  • sloc: makefile: 13
file content (135 lines) | stat: -rw-r--r-- 5,441 bytes parent folder | download
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")
	}
}