autogenpb/main.go

159 lines
3.7 KiB
Go

//go:build go1.20
// +build go1.20
package main
import (
"errors"
"os"
"strings"
"github.com/alexflint/go-arg"
"go.wit.com/lib/gui/shell"
"go.wit.com/lib/protobuf/forgepb"
"go.wit.com/log"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
// sent via -ldflags
var VERSION string
var BUILDTIME string
var sortmap map[string]string
var forge *forgepb.Forge // forgepb figures out how to run protoc correctly if it's needed
var marshalKeys []string
var uniqueKeys []string
func main() {
pp := arg.MustParse(&argv)
// you need a proto file
if argv.Proto == "" {
log.Info("you must provide --proto <filename>")
os.Exit(-1)
}
if !shell.Exists(argv.Proto) {
log.Info("protobuf", argv.Proto, "is missing")
if !argv.DryRun {
os.Exit(-1)
}
}
if !strings.HasSuffix(argv.Proto, ".proto") {
log.Info("protobuf", argv.Proto, "must end in .proto")
os.Exit(-1)
}
// you need --upbase and --lobase
if argv.Proto == "" {
pp.WriteHelp(os.Stdout)
os.Exit(-1)
}
if !shell.Exists("go.sum") {
shell.Run([]string{"go", "mod", "init"})
shell.Run([]string{"go", "mod", "tidy"})
}
cmd := []string{"go", "list", "-f", "'{{.Name}}'"}
result := shell.Run(cmd)
packageName := strings.Join(result.Stdout, "\n")
packageName = strings.TrimSpace(packageName)
packageName = strings.Trim(packageName, "'")
log.Info("packageName == ", packageName)
protobase := strings.TrimSuffix(argv.Proto, ".proto")
sortmap = make(map[string]string)
sortmap["package"] = packageName
sortmap["protofile"] = argv.Proto
sortmap["protobase"] = protobase
if argv.LoBase == "" {
// if not set, assumed to be protobase
sortmap["base"] = protobase
} else {
sortmap["base"] = argv.LoBase
}
sortmap["lock"] = sortmap["base"] + "sMu" // is nonglobal and plural
if argv.UpBase == "" {
sortmap["Base"] = cases.Title(language.English, cases.NoLower).String(protobase)
sortmap["Bases"] = sortmap["Base"] + "s"
} else {
sortmap["Base"] = argv.UpBase
sortmap["Bases"] = sortmap["Base"] + "s"
}
if argv.DryRun {
for k, v := range sortmap {
log.Info(k, "=", v)
}
os.Exit(0)
}
// parse sort & marshal options from the .proto file
if err := findAutogenpb(sortmap); err != nil {
log.Info("autogenpb parse error:", err)
os.Exit(-1)
}
// try to make foo.pb.go with protoc if it's not here
sortmap["protoc"] = protobase + ".pb.go"
if !shell.Exists(sortmap["protoc"]) {
if err := protocBuild(sortmap); err != nil {
log.Info("protoc build error:", err)
os.Exit(-1)
}
// experiment to add a mutex to the structs.
// this might fix my other not so great lock implementation on sort (?)
// not sure though because I haven't tried it. leave it here until
// I can test it
if err := addMutex(sortmap); err == nil {
log.Info("adding mutex to existing protoc-gen-go file worked")
sortmap["mutex"] = "true"
sortmap["lock"] = "all"
} else {
log.Info("adding mutex to existing protoc-gen-go file did not work")
sortmap["mutex"] = "false"
}
}
// if foo.pb.go still doesn't exist, protoc failed
// exit here
if !shell.Exists(sortmap["protoc"]) {
log.Info("protoc build error.", sortmap["protoc"], "failed to be created with protoc and proto-gen-go")
badExit(errors.New("failed to be created with protoc and proto-gen-go"))
}
if argv.NoSort {
log.Info("not making sort.pb.go file (--no-sort == true)")
} else {
if len(uniqueKeys) != 0 {
}
makeSortfile()
}
if argv.NoMarshal {
log.Info("not making marshal.pb.go file (--no-marshal == true)")
} else {
if len(marshalKeys) != 0 {
}
// make the foo.marshal.pb.go file
marshal(sortmap)
}
}
func okExit(s string) {
log.Info("autogenpb ok", s)
os.Exit(0)
}
func badExit(err error) {
log.Info("autogenpb error:", err)
os.Exit(-1)
}