diff --git a/Makefile b/Makefile index ffdafa2..be9856e 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,10 @@ VERSION = $(shell git describe --tags) BUILDTIME = $(shell date +%Y.%m.%d_%H%M) -full: install clean auto goimports vet build test +simple: build + make -C example simple goimports vet + +full: install clean auto goimports vet build test install @echo everything worked and the example ran test: goimports build test @@ -17,7 +20,7 @@ recover: make goimports make build -build: +build: goimports GO111MODULE=off go build \ -ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}" # autogen uses autogen to build. keep a working copy somewhere diff --git a/addMutex.go b/addMutex.go index 12ea1d0..ff2aec5 100644 --- a/addMutex.go +++ b/addMutex.go @@ -24,7 +24,7 @@ func (pb *Files) addMutex(f *File) error { // check if autogenpb has already looked at this file for _, line := range strings.Split(string(data), "\n") { if strings.Contains(line, "autogenpb DO NOT EDIT") { - log.Info("autogenpb has already been run") + log.Info("autogenpb has already been run on", fullname) return nil } } diff --git a/example/Makefile b/example/Makefile index 1f3d285..e2673c3 100644 --- a/example/Makefile +++ b/example/Makefile @@ -16,13 +16,18 @@ vet: build: GO111MODULE=off go build -v +simple: + ../autogenpb --proto fruit.proto --package main + withMutex: ../autogenpb --proto fruit.proto --package main ../autogenpb --proto file.proto --package main + ../autogenpb --proto patchset.proto --package main withoutMutex: ../autogenpb --proto fruit.proto --package main --mutex=false ../autogenpb --proto file.proto --package main --mutex=false + ../autogenpb --proto patchset.proto --package main --mutex=false goimports: goimports -w *.go diff --git a/example/patchset.proto b/example/patchset.proto new file mode 100644 index 0000000..e5d56b9 --- /dev/null +++ b/example/patchset.proto @@ -0,0 +1,37 @@ +syntax = "proto3"; + +package forgepb; + +import "google/protobuf/timestamp.proto"; // Import the well-known type for Timestamp + +message Patch { + string filename = 1; // `autogenpb:unique` `autogenpb:sort` + bytes data = 2; // + string repoPath = 3; // path to the git repo + string branchName = 4; // + string branchHash = 5; // + google.protobuf.Timestamp ctime = 7; // the git commit timestamp of this patch + string commitHash = 8; // the git commit hash of this patch + string startHash = 9; // the start commit hash + repeated string Files = 10; // the filenames this patch changes +} + +message Patchset { // `autogenpb:marshal` + repeated Patch Patches = 1; // + string name = 2; // + string comment = 3; // + string gitAuthorName = 4; // + string gitAuthorEmail = 5; // + google.protobuf.Timestamp ctime = 6; // create time of this patchset + string tmpDir = 7; // temp dir + string startBranchName = 8; // + string endBranchName = 9; // + string startBranchHash = 10; // + string endBranchHash = 11; // +} + +message Patchsets { // `autogenpb:marshal` + string uuid = 1; // `autogenpb:uuid:be926ad9-f07f-484c-adf2-d96eeabf3079` // todo: add autogenpb support for this + string version = 2; // `autogenpb:version:v0.0.45` // todo: add autogenpb support for this + repeated Patchset Patchsets = 3; +} diff --git a/file.proto b/file.proto index 18b096a..bb9f614 100644 --- a/file.proto +++ b/file.proto @@ -29,6 +29,8 @@ message MsgVar { string varName = 1; // the variable name string varType = 2; // the variable type bool isRepeated = 3; // does the variable repeate + bool hasSort = 4; // marked with sort + bool hasUnique = 5; // marked with unique } message MsgName { diff --git a/protoParse.go b/protoParse.go index 6403346..832601d 100644 --- a/protoParse.go +++ b/protoParse.go @@ -81,6 +81,7 @@ func (pb *Files) protoParse(f *File) error { prefix := "message " + base + " {" // only look for this for now if strings.HasPrefix(line, prefix) { f.Base = curmsg + f.MsgNames = append(f.MsgNames, curmsg) } else { f.MsgNames = append(f.MsgNames, curmsg) } @@ -93,13 +94,18 @@ func (pb *Files) protoParse(f *File) error { continue } - // log.Info("line:", line) parts := strings.Fields(line) + msgvar := parseMsgVar(line) + if msgvar == nil { + // log.Info("Junk in .proto file? line did not contain a message var:", line) + continue + } if strings.Contains(line, "autogenpb:sort") { newS := cases.Title(language.English, cases.NoLower).String(parts[1]) log.Info("Addded Sort:", newS, "in struct", curmsg.Name) curmsg.Sort = append(curmsg.Sort, newS) + msgvar.HasSort = true } if strings.Contains(line, "autogenpb:unique") { @@ -107,11 +113,43 @@ func (pb *Files) protoParse(f *File) error { newU = cases.Title(language.English, cases.NoLower).String(newU) log.Info("Added Unique:", newU, "in struct", curmsg.Name) curmsg.Unique = append(curmsg.Unique, newU) + msgvar.HasUnique = true } + curmsg.Vars = append(curmsg.Vars, msgvar) } return nil } +func parseMsgVar(line string) *MsgVar { + if strings.Contains(line, "//") { + parts := strings.Split(line, "//") + if len(parts) == 0 { + // log.Info("parseMsgVar() nothing line", line) + return nil + } + line = parts[0] + } + parts := strings.Fields(line) + if len(parts) < 3 { + // log.Info("parseMsgVar() len < 3", parts) + return nil + } + if parts[0] == "message" { + // this is the struct + return nil + } + v := new(MsgVar) + if parts[0] == "repeated" { + v.IsRepeated = true + v.VarType = parts[1] + v.VarName = parts[2] + return v + } + v.VarType = parts[0] + v.VarName = parts[1] + return v +} + // looks for mutex and marshal entries func (f *File) parseForMessage(line string) *MsgName { fields := strings.Fields(line) diff --git a/sort.go b/sort.go index 44b0798..b1ad4dd 100644 --- a/sort.go +++ b/sort.go @@ -3,35 +3,115 @@ package main import ( "fmt" "os" + + "go.wit.com/log" + "golang.org/x/text/cases" + "golang.org/x/text/language" ) // this file is named poorly. It has more than Sort() func (pb *Files) makeNewSortfile(pf *File) error { - w, _ := os.OpenFile(pf.Filebase+".sort.pb.go", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + wSort, _ := os.OpenFile(pf.Filebase+".sort.pb.go", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + defer wSort.Close() + wFind, _ := os.OpenFile(pf.Filebase+".find.pb.go", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + defer wFind.Close() - header(w, pf) - pf.syncLock(w) + header(wSort, pf) + header(wFind, pf) + + if !argv.Mutex { + pf.syncLock(wSort) + } if argv.Mutex { // use the mutex lock from the modified protoc.pb.go file pf.Bases.Lockname = "all.Lock" } - pf.Base.iterTop(w) - pf.Base.iterNext(w) - pf.selectAllFunc(w) - pf.iterSelect(w) + pf.Base.iterTop(wSort) + pf.Base.iterNext(wSort) + pf.selectAllFunc(wSort) + pf.iterSelect(wSort) - fmt.Fprintln(w, "// maybe seperate files here?") - - pf.appendUnique(w) // Append() enforce no unique keys - pf.sortByFunc(w) + pf.appendUnique(wFind) // Append() enforce no unique keys + pf.sortByFunc(wSort) if argv.Delete { - pf.deleteWithCopyFunc(w) + pf.deleteWithCopyFunc(wFind) } else { - pf.deleteFunc(w) + pf.deleteFunc(wFind) } - pf.findFunc(w) + pf.findFunc(wFind) + + // show the protobuf of the protobuf. Inception 2025 + pf.printMsgTable() + + // attempt to add sort functions for pf.Base + pf.processMessage(pf.Base) return nil } + +func (pf *File) processMessage(msg *MsgName) error { + log.Printf("%s\n", msg.Name) + for _, v := range msg.Vars { + if !v.IsRepeated { + // log.Printf("\tSKIP %s %s\n", v.VarName, v.VarType) + continue + } + if err := pf.addSortByMsg(msg, v); err != nil { + return err + } + } + return nil +} + +func (pf *File) addSortByMsg(parent *MsgName, find *MsgVar) error { + // log.Printf("\tLOOK HERE: %s %s\n", find.VarName, find.VarType) + var found *MsgName + for _, msg := range pf.MsgNames { + if msg.Name == find.VarType { + found = msg + break + } + } + if found == nil { + return fmt.Errorf("failed to find struct %s", find.VarType) + } + log.Printf("FOUND!: %s %s for %s\n", find.VarName, find.VarType, found.Name) + for _, v := range found.Vars { + if v.HasSort { + // log.Printf("\tSort!: %s %s for %s\n", find.VarName, find.VarType, v.VarName) + newS := cases.Title(language.English, cases.NoLower).String(v.VarName) + log.Printf("\t(x %s) SortdBy%s() *%sIter\n", parent.Name, newS, find.VarType) + } + if v.HasUnique { + // log.Printf("\tUniq!: %s %s for %s\n", find.VarName, find.VarType, v.VarName) + newS := cases.Title(language.English, cases.NoLower).String(v.VarName) + log.Printf("\t(x %s) AppendUniqueBy%s(%s)\n", parent.Name, newS, find.VarType) + log.Printf("\t(x %s) FindBy%s(string) *%s\n", parent.Name, newS, find.VarType) + if v.VarType == "string" { + log.Printf("\t(x %s) DeleteBy%s(string) *%s\n", parent.Name, newS, find.VarType) + } + } + } + return nil +} + +func (pf *File) printMsgTable() { + for _, msg := range pf.MsgNames { + log.Printf("%s\n", msg.Name) + for _, v := range msg.Vars { + var end string + if v.IsRepeated { + end += "(repeated) " + } + if v.HasSort { + end += "(sort) " + } + if v.HasUnique { + end += "(unique) " + } + log.Printf("\t%s %s %s\n", v.VarName, v.VarType, end) + } + } +}