diff --git a/Makefile b/Makefile index 08330c2..a9ba393 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ simple: test # make -C example clean simpleMutexProtoc goimports vet # make -C example deleteproto -full: install clean auto goimports vet build test install +full: clean auto goimports vet build test install @echo everything worked and the example ran # does a help example to debug the help logic diff --git a/example/Makefile b/example/Makefile index 40c0146..d158441 100644 --- a/example/Makefile +++ b/example/Makefile @@ -8,6 +8,9 @@ all: clean simpleMutexProtoc goimports build # and it is OK to 'go install' the binary test: testGlobal testProtoc +toy: + ../autogenpb --proto toy.proto --package main + testGlobal: make clean ../autogenpb --proto fruit.proto --package main --mutex=false # first build with a global mutex diff --git a/example/toy.proto b/example/toy.proto new file mode 100644 index 0000000..a425a0a --- /dev/null +++ b/example/toy.proto @@ -0,0 +1,34 @@ +syntax = "proto3"; + + +package main; + +import "google/protobuf/timestamp.proto"; // Import the well-known type for Timestamp + +message Basket { // `autogenpb:nomutex` + repeated string name = 1; // `autogenpb:sort` `autogenpb:unique` + string favorite = 2; // `autogenpb:sort` `autogenpb:unique` + int64 price = 3; // `autogenpb:sort` + repeated Banana banna = 4; + repeated Pear pears = 5; + repeated Apple stacks = 6; +} + +// "Fruit" must exist. you can put anything in it +message Toy { + string brand = 1; // `autogenpb:unique` `autogenpb:sort` + repeated Apple apples = 2; + string name = 4; // `autogenpb:sort` `autogenpb:unique` + string UPC = 4; // `autogenpb:sort` `autogenpb:unique` + string city = 5; // `autogenpb:sort` + repeated Basket Baskets = 8; + map who = 9; + int64 cost = 10; +} + +message Toys { // `autogenpb:marshal` `autogenpb:mutex` + string uuid = 1; // `autogenpb:uuid:be456ad9-f07f-484c-adf2-d96eeabf3079` + string version = 2; // `autogenpb:version:v0.0.1` + repeated Toy Toys = 3; // THIS MUST BE "Fruit" and then "Fruit" + "s" + // you can add additional things here but the three lines above must conform to the standard above +} diff --git a/generate.go b/generate.go index 7e42447..717393d 100644 --- a/generate.go +++ b/generate.go @@ -68,6 +68,7 @@ func (pb *Files) makeNewSortfile(pf *File) error { funcdef := msg.newIterAll(wSort, FRUIT, APPLE, APPLES, LOCK) log.Printf("JUNK: %-2d %20s %20s %20s %20s %s\n", i, FRUIT, APPLE, "", LOCK, funcdef) + log.Printf("JUNK: %-2d %20s %20s %20s %20s %s\n", i, FRUIT, APPLE, "", LOCK, funcdef) } log.Printf("\n") diff --git a/human.go b/human.go index bd27580..6c96bd1 100644 --- a/human.go +++ b/human.go @@ -2,8 +2,13 @@ package main import ( "fmt" + "os/exec" + "github.com/go-cmd/cmd" + "github.com/google/uuid" "go.wit.com/log" + "golang.org/x/text/cases" + "golang.org/x/text/language" ) // This was just going to be a function to print the results to stdout @@ -122,3 +127,81 @@ func (msg *MsgName) printMsg() { log.Printf("\t%s %s %s\n", v.VarName, v.VarType, end) } } + +func checkCmd(cmd string) { + path, err := exec.LookPath(cmd) + if err != nil { + fmt.Printf("\n%s is not in the PATH\n", cmd) + userInstructions() + log.Sleep(2) + } else { + fmt.Printf("%s is available at %s\n", cmd, path) + } +} + +func (pf *File) noPluralMessage() { + base := cases.Title(language.English, cases.NoLower).String(pf.Filebase) + + log.Info("") + log.Info("###########################################################################") + log.Info("Your proto file", pf.Filename, "does not contain the correct 'message' definitions") + log.Info("") + log.Info("For autogenpb to work on your file", pf.Filename, ", you must have both names exactly:") + log.Info("") + log.Printf("message %s {\n", base) + log.Info("}") + log.Printf("message %s {\n", base+"s") + log.Info("}") + log.Info("") + log.Info("###########################################################################") + badExit(fmt.Errorf("proto file error %s", pf.Filename)) +} + +// message Fruits { // `autogenpb:marshal` `autogenpb:mutex` +// string uuid = 1; // `autogenpb:uuid:be926ad9-f07f-484c-adf2-d96eeabf3079` +// string version = 2; // `autogenpb:version:v0.0.1` +// repeated Fruit Fruits = 3; // THIS MUST BE "Fruit" and then "Fruit" + "s" +// } + +func (pf *File) noUuid() { + base := cases.Title(language.English, cases.NoLower).String(pf.Filebase) + id := uuid.New() + + log.Info("") + log.Info("###########################################################################") + log.Info("Your proto file", pf.Filename, "is incorrect for 'message' ", base+"s") + log.Info("") + log.Info("For autogenpb to work on your file", pf.Filename, ",", base+"s must be exactly:") + log.Info("") + log.Info("message", base+"s", "{ // `autogenpb:marshal` `autogenpb:mutex`") + log.Info(" string uuid = 1; // `autogenpb:uuid:" + id.String() + "`") + log.Info(" string version = 2; // `autogenpb:version:v0.0.1`") + log.Info(" repeated", base, base+"s", " = 3; // THIS MUST BE ", base, " and then ", base+"s") + log.Info("}") + log.Info("") + log.Info("If you don't have a UUID, you can use the randomly generated one here") + log.Info("") + log.Info("###########################################################################") + badExit(fmt.Errorf("proto file error %s", pf.Filename)) +} + +func userNotes(result cmd.Status) error { + log.Info("protoc failed", result.Cmd, "with", result.Exit) + for _, line := range result.Stdout { + log.Info("STDOUT:", line) + } + for _, line := range result.Stderr { + log.Info("STDERR:", line) + } + userInstructions() + return fmt.Errorf("protoc failed with %d %v", result.Exit, result.Error) +} + +func userInstructions() { + log.Info("This is likely because you don't have protoc and protoc-gen-go installed") + log.Info("") + log.Info("On debian, you can:") + log.Info(" apt install protobuf-compiler # for protoc") + log.Info(" apt install protoc-gen-go # for protoc-gen-go") + log.Info("") +} diff --git a/main.go b/main.go index d066507..41c8f77 100644 --- a/main.go +++ b/main.go @@ -145,10 +145,15 @@ func main() { // 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 + 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) { + checkCmd("protoc") + checkCmd("protoc-gen-go") + if err := pb.protocBuild(pf); err != nil { badExit(err) } diff --git a/protoParse.go b/protoParse.go index 8b6a313..53f1b6a 100644 --- a/protoParse.go +++ b/protoParse.go @@ -11,8 +11,6 @@ import ( "go.wit.com/log" "golang.org/x/text/cases" "golang.org/x/text/language" - - "github.com/google/uuid" ) // this parses the .proto file and handles anything with `autogenpb: ` @@ -65,52 +63,6 @@ func (pb *Files) hasPluralMessage(f *File) error { return fmt.Errorf("proto file error %s", f.Filename) } -func (pf *File) noPluralMessage() { - base := cases.Title(language.English, cases.NoLower).String(pf.Filebase) - - log.Info("") - log.Info("###########################################################################") - log.Info("Your proto file", pf.Filename, "does not contain the correct 'message' definitions") - log.Info("") - log.Info("For autogenpb to work on your file", pf.Filename, ", you must have both names exactly:") - log.Info("") - log.Printf("message %s {\n", base) - log.Info("}") - log.Printf("message %s {\n", base+"s") - log.Info("}") - log.Info("") - log.Info("###########################################################################") - badExit(fmt.Errorf("proto file error %s", pf.Filename)) -} - -// message Fruits { // `autogenpb:marshal` `autogenpb:mutex` -// string uuid = 1; // `autogenpb:uuid:be926ad9-f07f-484c-adf2-d96eeabf3079` -// string version = 2; // `autogenpb:version:v0.0.1` -// repeated Fruit Fruits = 3; // THIS MUST BE "Fruit" and then "Fruit" + "s" -// } - -func (pf *File) noUuid() { - base := cases.Title(language.English, cases.NoLower).String(pf.Filebase) - id := uuid.New() - - log.Info("") - log.Info("###########################################################################") - log.Info("Your proto file", pf.Filename, "is incorrect for 'message' ", base+"s") - log.Info("") - log.Info("For autogenpb to work on your file", pf.Filename, ",", base+"s must be exactly:") - log.Info("") - log.Info("message", base+"s", "{ // `autogenpb:marshal` `autogenpb:mutex`") - log.Info(" string uuid = 1; // `autogenpb:uuid:" + id.String() + "`") - log.Info(" string version = 2; // `autogenpb:version:v0.0.1`") - log.Info(" repeated", base, base+"s", " = 3; // THIS MUST BE ", base, " and then ", base+"s") - log.Info("}") - log.Info("") - log.Info("If you don't have a UUID, you can use the randomly generated one here") - log.Info("") - log.Info("###########################################################################") - badExit(fmt.Errorf("proto file error %s", pf.Filename)) -} - func (pb *Files) protoParse(pf *File) error { // does the file conform to the standard? (also reads in UUID & Version) if err := pb.hasPluralMessage(pf); err != nil { diff --git a/protoc.go b/protoc.go index f8297bc..3645b57 100644 --- a/protoc.go +++ b/protoc.go @@ -4,12 +4,10 @@ package main import ( "errors" - "fmt" "os" "path/filepath" "strings" - "github.com/go-cmd/cmd" "go.wit.com/lib/gui/shell" "go.wit.com/log" ) @@ -106,20 +104,3 @@ func runprotoc(pwd string, mycmd []string) error { } return nil } - -func userNotes(result cmd.Status) error { - log.Info("protoc failed", result.Cmd, "with", result.Exit) - for _, line := range result.Stdout { - log.Info("STDOUT:", line) - } - for _, line := range result.Stderr { - log.Info("STDERR:", line) - } - log.Info("This is likely because you don't have protoc and protoc-gen-go installed") - log.Info("") - log.Info("On debian, you can:") - log.Info(" apt install protobuf-compiler # for protoc") - log.Info(" apt install protoc-gen-go # for protoc-gen-go") - log.Info("") - return fmt.Errorf("protoc failed with %d %v", result.Exit, result.Error) -}