Skip to content

Commit

Permalink
Add buf generate --include-wkt (bufbuild#892)
Browse files Browse the repository at this point in the history
  • Loading branch information
bufdev authored Feb 4, 2022
1 parent f774812 commit fb07c55
Show file tree
Hide file tree
Showing 14 changed files with 286 additions and 97 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
- Check that the user provided a valid token when running `buf registry login`.
- Add `buf mod open` that opens a module's homepage in a browser.
- Add `buf completion` command to generate auto-completion scripts in commonly used shells.
- Add `--include-wkt` flag to `buf generate`. When this flag is specified alongside
`--include-imports`, this will result in the [Well-Known Types](https://github.com/bufbuild/wellknowntypes/tree/11ea259bf71c4d386131c1986ffe103cb1edb3d6/v3.19.4/google/protobuf)
being generated as well. Most language runtimes have the Well-Known Types included as part
of the core library, making generating the Well-Known Types separately undesirable.

## [v1.0.0-rc12] - 2022-02-01

Expand Down
12 changes: 11 additions & 1 deletion private/buf/bufgen/bufgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,23 @@ func GenerateWithBaseOutDirPath(baseOutDirPath string) GenerateOption {

// GenerateWithIncludeImports says to also generate imports.
//
// Note that this does NOT result in the Well-Known Types being generated.
// Note that this does NOT result in the Well-Known Types being generated, use
// GenerateWithIncludeWellKnownTypes to include the Well-Known Types.
func GenerateWithIncludeImports() GenerateOption {
return func(generateOptions *generateOptions) {
generateOptions.includeImports = true
}
}

// GenerateWithIncludeWellKnownTypes says to also generate well known types.
//
// This option has no effect if GenerateWithIncludeImports is not set.
func GenerateWithIncludeWellKnownTypes() GenerateOption {
return func(generateOptions *generateOptions) {
generateOptions.includeWellKnownTypes = true
}
}

// Config is a configuration.
type Config struct {
// Required
Expand Down
15 changes: 13 additions & 2 deletions private/buf/bufgen/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ func (g *generator) Generate(
image,
generateOptions.baseOutDirPath,
generateOptions.includeImports,
generateOptions.includeWellKnownTypes,
)
}

Expand All @@ -102,6 +103,7 @@ func (g *generator) generate(
image bufimage.Image,
baseOutDirPath string,
includeImports bool,
includeWellKnownTypes bool,
) error {
if err := modifyImage(ctx, g.logger, config, image); err != nil {
return err
Expand All @@ -113,6 +115,7 @@ func (g *generator) generate(
config,
image,
includeImports,
includeWellKnownTypes,
)
if err != nil {
return err
Expand Down Expand Up @@ -153,6 +156,7 @@ func (g *generator) execPlugins(
config *Config,
image bufimage.Image,
includeImports bool,
includeWellKnownTypes bool,
) ([]*pluginpb.CodeGeneratorResponse, error) {
imageProvider := newImageProvider(image)
// Collect all of the plugin jobs so that they can be executed in parallel.
Expand All @@ -169,6 +173,7 @@ func (g *generator) execPlugins(
image,
currentPluginConfig,
includeImports,
includeWellKnownTypes,
)
if err != nil {
return err
Expand All @@ -186,6 +191,7 @@ func (g *generator) execPlugins(
imageProvider,
currentPluginConfig,
includeImports,
includeWellKnownTypes,
)
if err != nil {
return err
Expand Down Expand Up @@ -232,6 +238,7 @@ func (g *generator) execLocalPlugin(
imageProvider *imageProvider,
pluginConfig *PluginConfig,
includeImports bool,
includeWellKnownTypes bool,
) (*pluginpb.CodeGeneratorResponse, error) {
pluginImages, err := imageProvider.GetImages(pluginConfig.Strategy)
if err != nil {
Expand All @@ -246,6 +253,7 @@ func (g *generator) execLocalPlugin(
pluginConfig.Opt,
nil,
includeImports,
includeWellKnownTypes,
),
appprotoexec.GenerateWithPluginPath(pluginConfig.Path),
)
Expand All @@ -261,6 +269,7 @@ func (g *generator) execRemotePlugin(
image bufimage.Image,
pluginConfig *PluginConfig,
includeImports bool,
includeWellKnownTypes bool,
) (*pluginpb.CodeGeneratorResponse, error) {
remote, owner, name, version, err := bufplugin.ParsePluginVersionPath(pluginConfig.Remote)
if err != nil {
Expand All @@ -287,6 +296,7 @@ func (g *generator) execRemotePlugin(
},
},
includeImports,
includeWellKnownTypes,
)
if err != nil {
return nil, err
Expand Down Expand Up @@ -470,8 +480,9 @@ func validateResponses(
}

type generateOptions struct {
baseOutDirPath string
includeImports bool
baseOutDirPath string
includeImports bool
includeWellKnownTypes bool
}

func newGenerateOptions() *generateOptions {
Expand Down
24 changes: 24 additions & 0 deletions private/buf/cmd/buf/command/generate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const (
configFlagName = "config"
pathsFlagName = "path"
includeImportsFlagName = "include-imports"
includeWKTFlagName = "include-wkt"
excludePathsFlagName = "exclude-path"

// deprecated
Expand Down Expand Up @@ -194,6 +195,7 @@ type flags struct {
Config string
Paths []string
IncludeImports bool
IncludeWKT bool
ExcludePaths []string

// deprecated
Expand All @@ -218,6 +220,15 @@ func (f *flags) Bind(flagSet *pflag.FlagSet) {
false,
"Also generate all imports except for Well-Known Types.",
)
flagSet.BoolVar(
&f.IncludeWKT,
includeWKTFlagName,
false,
fmt.Sprintf(
"Also generate Well-Known Types. Cannot be set without --%s.",
includeImportsFlagName,
),
)
flagSet.StringVar(
&f.Template,
templateFlagName,
Expand Down Expand Up @@ -274,6 +285,13 @@ func run(
flags *flags,
) (retErr error) {
logger := container.Logger()
if flags.IncludeWKT && !flags.IncludeImports {
// You need to set --include-imports if you set --include-wkt, which isn’t great. The alternative is to have
// --include-wkt implicitly set --include-imports, but this could be surprising. Or we could rename
// --include-wkt to --include-imports-and/with-wkt. But the summary is that the flag only makes sense
// in the context of including imports.
return appcmd.NewInvalidArgumentErrorf("Cannot set --%s without --%s", includeWKTFlagName, includeImportsFlagName)
}
if err := bufcli.ValidateErrorFormatFlag(flags.ErrorFormat, errorFormatFlagName); err != nil {
return err
}
Expand Down Expand Up @@ -370,6 +388,12 @@ func run(
bufgen.GenerateWithIncludeImports(),
)
}
if flags.IncludeWKT {
generateOptions = append(
generateOptions,
bufgen.GenerateWithIncludeWellKnownTypes(),
)
}
return bufgen.NewGenerator(
logger,
storageosProvider,
Expand Down
1 change: 1 addition & 0 deletions private/buf/cmd/buf/command/protoc/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ func executePlugin(
strings.Join(pluginInfo.Opt, ","),
appprotoexec.DefaultVersion,
false,
false,
),
appprotoexec.GenerateWithPluginPath(pluginInfo.Path),
)
Expand Down
2 changes: 1 addition & 1 deletion private/buf/cmd/protoc-gen-buf-lint/lint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,5 +289,5 @@ func testBuildCodeGeneratorRequest(
}
image, err := bufimage.NewImage(imageFiles)
require.NoError(t, err)
return bufimage.ImageToCodeGeneratorRequest(image, parameter, nil, false)
return bufimage.ImageToCodeGeneratorRequest(image, parameter, nil, false, false)
}
27 changes: 26 additions & 1 deletion private/bufpkg/bufimage/bufimage.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,17 +362,21 @@ func ImageToFileDescriptorProtos(image Image) []*descriptorpb.FileDescriptorProt
//
// All non-imports are added as files to generate.
// If includeImports is set, all non-well-known-type imports are also added as files to generate.
// If includeWellKnownTypes is set, well-known-type imports are also added as files to generate.
// includeWellKnownTypes has no effect if includeImports is not set.
func ImageToCodeGeneratorRequest(
image Image,
parameter string,
compilerVersion *pluginpb.Version,
includeImports bool,
includeWellKnownTypes bool,
) *pluginpb.CodeGeneratorRequest {
return imageToCodeGeneratorRequest(
image,
parameter,
compilerVersion,
includeImports,
includeWellKnownTypes,
nil,
nil,
)
Expand All @@ -383,17 +387,37 @@ func ImageToCodeGeneratorRequest(
// All non-imports are added as files to generate.
// If includeImports is set, all non-well-known-type imports are also added as files to generate.
// If includeImports is set, only one CodeGeneratorRequest will contain any given file as a FileToGenerate.
// If includeWellKnownTypes is set, well-known-type imports are also added as files to generate.
// includeWellKnownTypes has no effect if includeImports is not set.
func ImagesToCodeGeneratorRequests(
images []Image,
parameter string,
compilerVersion *pluginpb.Version,
includeImports bool,
includeWellKnownTypes bool,
) []*pluginpb.CodeGeneratorRequest {
requests := make([]*pluginpb.CodeGeneratorRequest, len(images))
// we don't need to track these if includeImports as false, so don't waste the time
// alreadyUsedPaths is a map of paths that have already been added to an image.
//
// We track this if includeImports is set, so that when we find an import, we can
// see if the import was already added to a CodeGeneratorRequest via another Image
// in the Image slice. If the import was already added, we do not add duplicates
// across CodeGeneratorRequests.
var alreadyUsedPaths map[string]struct{}
// nonImportPaths is a map of non-import paths.
//
// We track this if includeImports is set. If we find a non-import file in Image A
// and this file is an import in Image B, the file will have already been added to
// a CodeGeneratorRequest via Image A, so do not add the duplicate to any other
// CodeGeneratorRequest.
var nonImportPaths map[string]struct{}
if includeImports {
// We don't need to track these if includeImports is false, so we only populate
// the maps if includeImports is true. If includeImports is false, only non-imports
// will be added to each CodeGeneratorRequest, so figuring out whether or not
// we should add a given import to a given CodeGeneratorRequest is unnecessary.
//
// imageToCodeGeneratorRequest checks if these maps are nil before every access.
alreadyUsedPaths = make(map[string]struct{})
nonImportPaths = make(map[string]struct{})
for _, image := range images {
Expand All @@ -410,6 +434,7 @@ func ImagesToCodeGeneratorRequests(
parameter,
compilerVersion,
includeImports,
includeWellKnownTypes,
alreadyUsedPaths,
nonImportPaths,
)
Expand Down
5 changes: 1 addition & 4 deletions private/bufpkg/bufimage/bufimagemodify/bufimagemodify.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,10 +282,7 @@ func RubyPackage(

// isWellKnownType returns true if the given path is one of the well-known types.
func isWellKnownType(ctx context.Context, imageFile bufimage.ImageFile) bool {
if _, err := datawkt.ReadBucket.Stat(ctx, imageFile.Path()); err == nil {
return true
}
return false
return datawkt.Exists(imageFile.Path())
}

// int32SliceIsEqual returns true if x and y contain the same elements.
Expand Down
Loading

0 comments on commit fb07c55

Please sign in to comment.