/
protogen.go
80 lines (67 loc) · 3.13 KB
/
protogen.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package main
import (
"fmt"
"path/filepath"
"github.com/spf13/cobra"
"github.com/streamingfast/cli"
"github.com/streamingfast/cli/sflags"
"github.com/streamingfast/substreams/codegen"
"github.com/streamingfast/substreams/manifest"
"go.uber.org/zap"
)
var protogenCmd = &cobra.Command{
Use: "protogen [<manifest>]",
Short: "Generate Rust bindings from a package",
Long: cli.Dedent(`
Generate Rust bindings from a package. The manifest is optional as it will try to find a file named
'substreams.yaml' in current working directory if nothing entered. You may enter a directory that contains a 'substreams.yaml'
file in place of '<manifest_file>', or a link to a remote .spkg file, using urls gs://, http(s)://, ipfs://, etc.'.
Note: if you have a data structure with an attribute that starts with an underscore, buf generate will remove the underscore.
`),
RunE: runProtogen,
Args: cobra.RangeArgs(0, 1),
SilenceUsage: true,
}
func init() {
rootCmd.AddCommand(protogenCmd)
flags := protogenCmd.Flags()
flags.StringP("output-path", "o", "src/pb", cli.FlagDescription(`
Directory to output generated .rs files, if the received <package> argument is a local Substreams manifest file
(e.g. a local file ending with .yaml), the output path will be made relative to it
`))
flags.StringArrayP("exclude-paths", "x", []string{}, "Exclude specific files or directories, for example \"proto/a/a.proto\" or \"proto/a\"")
flags.Bool("generate-mod-rs", true, cli.FlagDescription(`
Generate the protobuf 'mod.rs' file alongside the rust bindings. Include '--generate-mod-rs=false' If you wish to disable this generation.
If there is a present 'buf.gen.yaml', consult https://github.com/neoeinstein/protoc-gen-prost/blob/main/protoc-gen-prost-crate/README.md to add 'mod.rs' generation functionality.
`))
flags.Bool("show-generated-buf-gen", false, "Whether to show the generated buf.gen.yaml file or not")
}
func runProtogen(cmd *cobra.Command, args []string) error {
outputPath := sflags.MustGetString(cmd, "output-path")
excludePaths := sflags.MustGetStringArray(cmd, "exclude-paths")
generateMod := sflags.MustGetBool(cmd, "generate-mod-rs")
showGeneratedBufGen := sflags.MustGetBool(cmd, "show-generated-buf-gen")
manifestPath := ""
if len(args) == 1 {
manifestPath = args[0]
}
readerOptions := []manifest.Option{
manifest.SkipSourceCodeReader(),
manifest.SkipModuleOutputTypeValidationReader(),
}
manifestReader, err := manifest.NewReader(manifestPath, readerOptions...)
if err != nil {
return fmt.Errorf("manifest reader: %w", err)
}
if manifestReader.IsLocalManifest() && !filepath.IsAbs(outputPath) {
newOutputPath := filepath.Join(filepath.Dir(manifestPath), outputPath)
zlog.Debug("manifest path is a local manifest, making output path relative to it", zap.String("old", outputPath), zap.String("new", newOutputPath))
outputPath = newOutputPath
}
pkg, _, err := manifestReader.Read()
if err != nil {
return fmt.Errorf("reading manifest %q: %w", manifestPath, err)
}
generator := codegen.NewProtoGenerator(outputPath, excludePaths, generateMod)
return generator.GenerateProto(pkg, showGeneratedBufGen)
}