autogenpb/main.go

176 lines
4.4 KiB
Go
Raw Normal View History

//go:build go1.20
2024-11-29 21:49:11 -06:00
// +build go1.20
2025-01-09 06:47:35 -06:00
// protobuf the way I am using them, require GO 1.20. I think. I could be wrong.
// The Go Protocol Buffers library embeds a sync.Mutex within the MessageState struct to prevent unintended shallow copies of message structs
// this optionally (but it is the default) inserts a mutex into the struct generated by protoc
2025-01-09 06:47:35 -06:00
// go:generate autogenpb --proto file.proto
2025-01-09 06:47:35 -06:00
2024-11-29 08:30:19 -06:00
package main
import (
"errors"
"fmt"
2024-11-29 08:30:19 -06:00
"os"
"path/filepath"
"strings"
"github.com/alexflint/go-arg"
"github.com/go-cmd/cmd"
"go.wit.com/lib/gui/shell"
"go.wit.com/log"
2024-11-29 08:30:19 -06:00
)
// sent via -ldflags
var VERSION string
var BUILDTIME string
// var fsort *os.File // the sort.pb.go output file
2024-11-29 08:30:19 -06:00
func main() {
pp := arg.MustParse(&argv)
var pb *Files
pb = new(Files)
// you need a proto file
if argv.Proto == "" {
log.Info("you must provide --proto <filename>")
2024-12-01 22:21:09 -06:00
pp.WriteHelp(os.Stdout)
os.Exit(-1)
}
if !shell.Exists(argv.Proto) {
log.Info("protobuf", argv.Proto, "is missing")
os.Exit(-1)
}
if !strings.HasSuffix(argv.Proto, ".proto") {
log.Info("protobuf", argv.Proto, "must end in .proto")
os.Exit(-1)
}
pf := new(File)
pb.Files = append(pb.Files, pf)
pf.Filename = argv.Proto
pf.IterMap = make(map[string]string)
pf.Filebase = strings.TrimSuffix(argv.Proto, ".proto")
// parse sort & marshal options from the .proto file
// this goes through the .proto files and looks
// for `autogenpb: ` lines
if err := pb.protoParse(pf); err != nil {
log.Info("autogenpb parse error:", err)
badExit(err)
}
if pf.Bases == nil {
badExit(fmt.Errorf("Base was nil. 'message %s {` did not exist", pf.Filebase))
}
if pf.Base == nil {
badExit(fmt.Errorf("Base was nil. 'message %s {` did not exist", pf.Filebase))
}
// if you have gotten here, at least the .proto buf file is OK
if argv.DryRun {
2025-01-12 09:40:18 -06:00
// show the protobuf of the protobuf. It's like Inception
pf.printMsgTable()
okExit("")
}
// todo, look for go.work files
2024-12-17 06:34:27 -06:00
if argv.GoSrc == "" {
homeDir, _ := os.UserHomeDir()
argv.GoSrc = filepath.Join(homeDir, "go/src")
2024-12-17 06:34:27 -06:00
}
2024-12-04 15:35:27 -06:00
2024-12-17 06:34:27 -06:00
if argv.GoPath == "" {
pwd, _ := os.Getwd()
argv.GoPath = strings.TrimPrefix(pwd, argv.GoSrc)
argv.GoPath = strings.Trim(argv.GoPath, "/")
2024-12-04 15:35:27 -06:00
}
2024-12-17 06:34:27 -06:00
log.Info(argv.GoSrc, argv.GoPath)
2024-12-04 15:35:27 -06:00
pwd, _ := os.Getwd()
log.Info("pwd = ", pwd)
if !shell.Exists("go.sum") {
2025-01-09 04:03:30 -06:00
shell.RunQuiet([]string{"go-mod-clean"})
if !shell.Exists("go.sum") {
shell.RunQuiet([]string{"go", "mod", "init"})
shell.RunQuiet([]string{"go", "mod", "tidy"})
shell.RunQuiet([]string{"go", "mod", "edit", "-go=1.18"}) // TODO: pass this as ENV. verify protobuf version needed
}
}
var packageName string
var result cmd.Status
var cmd []string
if argv.Package == "" {
2025-01-09 04:03:30 -06:00
// TODO: switch to using forgepb (expose the functions/logic from forgepb directly
// it could be a bad idea to use forge.Init() here as forge needs this to build
// switch to forgepb
os.Setenv("GO111MODULE", "off") // keeps go list working if go version is back versioned for compatability
cmd = []string{"go", "list", "-f", "'{{.Name}}'"}
result = shell.RunQuiet(cmd)
os.Unsetenv("GO111MODULE")
packageName = strings.Join(result.Stdout, "\n")
packageName = strings.TrimSpace(packageName)
packageName = strings.Trim(packageName, "'")
// log.Info("packageName == ", packageName)
} else {
packageName = argv.Package
}
pf.Package = packageName
2024-11-30 13:48:50 -06:00
// try to make foo.pb.go with protoc if it's not here
// this is helpful because the protoc-gen-go lines
// are also annoying to code by hand
2025-01-12 09:28:58 -06:00
checkCmd("protoc")
checkCmd("protoc-gen-go")
pf.Pbfilename = pf.Filebase + ".pb.go"
// try to create the foo.pb.go file using protoc if it is not there
if !shell.Exists(pf.Pbfilename) {
2025-01-12 09:28:58 -06:00
checkCmd("protoc")
checkCmd("protoc-gen-go")
if err := pb.protocBuild(pf); err != nil {
badExit(err)
}
}
2024-11-30 13:48:50 -06:00
// try to add the Mutex to the pb.go file
if err := pb.addMutex(pf); err != nil {
badExit(err)
}
2024-11-30 13:48:50 -06:00
// if foo.pb.go still doesn't exist, protoc failed
if !shell.Exists(pf.Pbfilename) {
log.Info("protoc build error.", pf.Pbfilename)
badExit(errors.New("failed to be created with protoc and proto-gen-go"))
2024-11-30 13:48:50 -06:00
}
// make the marshal.pb.go file
pb.marshal(pf)
// make the sort.pb.go file
if err := pb.makeNewSortfile(pf); err != nil {
badExit(err)
}
}
func okExit(s string) {
log.Info("autogenpb ok", s)
os.Exit(0)
}
func badExit(err error) {
log.Info("autogenpb error:", err)
os.Exit(-1)
}