From 07d2568d01f638fd13e08850591a66001ecd5022 Mon Sep 17 00:00:00 2001 From: bufdotbuild <4228796+bufdotbuild@users.noreply.github.com> Date: Mon, 14 Oct 2019 14:04:40 -0400 Subject: [PATCH] Allow @ to be used for -protoset --- cmd/grpcurl/grpcurl.go | 15 +++++++++++++-- desc_source.go | 16 +++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/cmd/grpcurl/grpcurl.go b/cmd/grpcurl/grpcurl.go index aaa3bbf..35f4eb2 100644 --- a/cmd/grpcurl/grpcurl.go +++ b/cmd/grpcurl/grpcurl.go @@ -72,7 +72,8 @@ var ( requests. It defaults to the given address.`)) data = flags.String("d", "", prettify(` Data for request contents. If the value is '@' then the request contents - are read from stdin. For calls that accept a stream of requests, the + are read from stdin. Note that '@' cannot be used for both -data and -protoset + in the same invocation. For calls that accept a stream of requests, the contents should include all such request messages concatenated together (possibly delimited; see -format).`)) format = flags.String("format", "json", prettify(` @@ -139,7 +140,9 @@ func init() { those exposed by the remote server), and the 'describe' action describes symbols found in the given descriptors. May specify more than one via multiple -protoset flags. It is an error to use both -protoset and - -proto flags.`)) + -proto flags. If the value is '@' then the protoset is read from stdin. + Note that '@' cannot be used for both -data and -protoset in the same + invocation.`)) flags.Var(&protoFiles, "proto", prettify(` The name of a proto source file. Source files given will be used to determine the RPC schema instead of querying for it from the remote @@ -278,6 +281,14 @@ func main() { warn("The -import-path argument is not used unless -proto files are used.") } + if *data == "@" && len(protoset) > 0 { + for _, fileName := range protoset { + if fileName == "@" { + fail(nil, "Cannot use '@' for both -data and -protoset.") + } + } + } + ctx := context.Background() if *maxTime > 0 { timeout := time.Duration(*maxTime * float64(time.Second)) diff --git a/desc_source.go b/desc_source.go index 635ddef..c4af941 100644 --- a/desc_source.go +++ b/desc_source.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "io/ioutil" + "os" "sync" "github.com/golang/protobuf/proto" @@ -38,10 +39,23 @@ type DescriptorSource interface { // DescriptorSourceFromProtoSets creates a DescriptorSource that is backed by the named files, whose contents // are encoded FileDescriptorSet protos. +// +// The special fileName "@" denotes to read from os.Stdin. Multiple "@" values will result +// in only one read from stdin. func DescriptorSourceFromProtoSets(fileNames ...string) (DescriptorSource, error) { + stdinProcessed := false files := &descpb.FileDescriptorSet{} for _, fileName := range fileNames { - b, err := ioutil.ReadFile(fileName) + var b []byte + var err error + if fileName == "@" { + if !stdinProcessed { + stdinProcessed = true + b, err = ioutil.ReadAll(os.Stdin) + } + } else { + b, err = ioutil.ReadFile(fileName) + } if err != nil { return nil, fmt.Errorf("could not load protoset file %q: %v", fileName, err) }