Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <psteinhardt@gitlab.com>2022-05-02 10:39:20 +0300
committerPatrick Steinhardt <psteinhardt@gitlab.com>2022-05-06 11:44:31 +0300
commitba661eea55984bd4ab0c00f15c2dfa07efb07cb7 (patch)
treeb6231a2ca5a91507c7f291877ae6fbba76963ca9 /tools/protoc-gen-gitaly-protolist
parent1466804c6e8e1cd5e237349998e0fca370ca3855 (diff)
tools: Move Protoc plugins into top-level `tools/` directory
The Protoc plugins we use are hidden away deep into the `proto/` directory, which makes it very hard to discover them when one doesn't already know about their existence. Let's move them into a new top-level `tools/` directory.
Diffstat (limited to 'tools/protoc-gen-gitaly-protolist')
-rw-r--r--tools/protoc-gen-gitaly-protolist/main.go139
1 files changed, 139 insertions, 0 deletions
diff --git a/tools/protoc-gen-gitaly-protolist/main.go b/tools/protoc-gen-gitaly-protolist/main.go
new file mode 100644
index 000000000..7e775360e
--- /dev/null
+++ b/tools/protoc-gen-gitaly-protolist/main.go
@@ -0,0 +1,139 @@
+// Command protoc-gen-gitaly-protolist is designed to be used as a protobuf compiler to generate a
+// list of protobuf files via a publicly accessible variable.
+//
+// This plugin can be accessed by invoking the protoc compiler with the following arguments:
+//
+// protoc --plugin=protoc-gen-gitaly-protolist --gitaly_protolist_out=.
+//
+// The plugin accepts a protobuf message in STDIN that describes the parsed protobuf files. A
+// response is sent back on STDOUT that contains any errors.
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/format"
+ "io"
+ "log"
+ "os"
+ "path/filepath"
+ "strings"
+ "text/template"
+
+ "google.golang.org/protobuf/proto"
+ "google.golang.org/protobuf/types/pluginpb"
+)
+
+const (
+ gitalyProtoDirArg = "proto_dir"
+ gitalypbDirArg = "gitalypb_dir"
+)
+
+func main() {
+ data, err := io.ReadAll(os.Stdin)
+ if err != nil {
+ log.Fatalf("reading input: %s", err)
+ }
+
+ req := &pluginpb.CodeGeneratorRequest{}
+
+ if err := proto.Unmarshal(data, req); err != nil {
+ log.Fatalf("parsing input proto: %s", err)
+ }
+
+ if err := generateProtolistGo(req); err != nil {
+ log.Fatal(err)
+ }
+}
+
+func parseArgs(argString string) (gitalyProtoDir string, gitalypbDir string) {
+ for _, arg := range strings.Split(argString, ",") {
+ argKeyValue := strings.Split(arg, "=")
+ if len(argKeyValue) != 2 {
+ continue
+ }
+ switch argKeyValue[0] {
+ case gitalyProtoDirArg:
+ gitalyProtoDir = argKeyValue[1]
+ case gitalypbDirArg:
+ gitalypbDir = argKeyValue[1]
+ }
+ }
+
+ return gitalyProtoDir, gitalypbDir
+}
+
+func generateProtolistGo(req *pluginpb.CodeGeneratorRequest) error {
+ var err error
+ gitalyProtoDir, gitalypbDir := parseArgs(req.GetParameter())
+
+ if gitalyProtoDir == "" {
+ return fmt.Errorf("%s not provided", gitalyProtoDirArg)
+ }
+ if gitalypbDir == "" {
+ return fmt.Errorf("%s not provided", gitalypbDirArg)
+ }
+
+ var protoNames []string
+
+ if gitalyProtoDir, err = filepath.Abs(gitalyProtoDir); err != nil {
+ return fmt.Errorf("failed to get absolute path for %s: %v", gitalyProtoDir, err)
+ }
+
+ files, err := os.ReadDir(gitalyProtoDir)
+ if err != nil {
+ return fmt.Errorf("failed to read %s: %v", gitalyProtoDir, err)
+ }
+
+ for _, fi := range files {
+ if !fi.IsDir() && strings.HasSuffix(fi.Name(), ".proto") {
+ protoNames = append(protoNames, fmt.Sprintf(`"%s"`, fi.Name()))
+ }
+ }
+
+ f, err := os.Create(filepath.Join(gitalypbDir, "protolist.go"))
+ if err != nil {
+ return fmt.Errorf("could not create protolist.go: %v", err)
+ }
+ defer f.Close()
+
+ if err = renderProtoList(f, protoNames); err != nil {
+ return fmt.Errorf("could not render go code: %v", err)
+ }
+
+ return nil
+}
+
+// renderProtoList generate a go file with a list of gitaly protos
+func renderProtoList(dest io.WriteCloser, protoNames []string) error {
+ joinFunc := template.FuncMap{"join": strings.Join}
+ protoList := `package gitalypb
+ // Code generated by protoc-gen-gitaly. DO NOT EDIT
+
+ // GitalyProtos is a list of gitaly protobuf files
+ var GitalyProtos = []string{
+ {{join . ",\n"}},
+ }
+ `
+ protoListTempl, err := template.New("protoList").Funcs(joinFunc).Parse(protoList)
+ if err != nil {
+ return fmt.Errorf("could not create go code template: %v", err)
+ }
+
+ var rawGo bytes.Buffer
+
+ if err := protoListTempl.Execute(&rawGo, protoNames); err != nil {
+ return fmt.Errorf("could not execute go code template: %v", err)
+ }
+
+ formattedGo, err := format.Source(rawGo.Bytes())
+ if err != nil {
+ return fmt.Errorf("could not format go code: %v", err)
+ }
+
+ if _, err = io.Copy(dest, bytes.NewBuffer(formattedGo)); err != nil {
+ return fmt.Errorf("failed to write protolist.go file: %v", err)
+ }
+
+ return nil
+}