161 lines
4.5 KiB
Go
161 lines
4.5 KiB
Go
// Copyright 2020-2021 Buf Technologies, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Package bufgen does configuration-based generation.
|
|
//
|
|
// It is used by the buf generate command.
|
|
package bufgen
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strconv"
|
|
|
|
"github.com/bufbuild/buf/internal/buf/bufcore/bufimage"
|
|
"github.com/bufbuild/buf/internal/pkg/app"
|
|
"github.com/bufbuild/buf/internal/pkg/storage/storageos"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// ExternalConfigV1Beta1FilePath is the default external configuration file path for v1beta1.
|
|
const ExternalConfigV1Beta1FilePath = "buf.gen.yaml"
|
|
|
|
const (
|
|
// StrategyDirectory is the strategy that says to generate per directory.
|
|
//
|
|
// This is the default value.
|
|
StrategyDirectory Strategy = 1
|
|
// StrategyAll is the strategy that says to generate with all files at once.
|
|
StrategyAll Strategy = 2
|
|
)
|
|
|
|
// Strategy is a generation stategy.
|
|
type Strategy int
|
|
|
|
// ParseStrategy parses the Strategy.
|
|
//
|
|
// If the empty string is provided, this is interpreted as StrategyDirectory.
|
|
func ParseStrategy(s string) (Strategy, error) {
|
|
switch s {
|
|
case "", "directory":
|
|
return StrategyDirectory, nil
|
|
case "all":
|
|
return StrategyAll, nil
|
|
default:
|
|
return 0, fmt.Errorf("unknown strategy: %s", s)
|
|
}
|
|
}
|
|
|
|
// String implements fmt.Stringer.
|
|
func (s Strategy) String() string {
|
|
switch s {
|
|
case StrategyDirectory:
|
|
return "directory"
|
|
case StrategyAll:
|
|
return "all"
|
|
default:
|
|
return strconv.Itoa(int(s))
|
|
}
|
|
}
|
|
|
|
// Generator generates Protobuf stubs based on configurations.
|
|
type Generator interface {
|
|
// Generate calls the generation logic.
|
|
//
|
|
// The config is assumed to be valid. If created by ReadConfig, it will
|
|
// always be valid.
|
|
Generate(
|
|
ctx context.Context,
|
|
container app.EnvStdioContainer,
|
|
config *Config,
|
|
image bufimage.Image,
|
|
options ...GenerateOption,
|
|
) error
|
|
}
|
|
|
|
// NewGenerator returns a new Generator.
|
|
func NewGenerator(
|
|
logger *zap.Logger,
|
|
storageosProvider storageos.Provider,
|
|
) Generator {
|
|
return newGenerator(logger, storageosProvider)
|
|
}
|
|
|
|
// GenerateOption is an option for Generate.
|
|
type GenerateOption func(*generateOptions)
|
|
|
|
// GenerateWithBaseOutDirPath returns a new GenerateOption that uses the given
|
|
// base directory as the output directory.
|
|
//
|
|
// The default is to use the current directory.
|
|
func GenerateWithBaseOutDirPath(baseOutDirPath string) GenerateOption {
|
|
return func(generateOptions *generateOptions) {
|
|
generateOptions.baseOutDirPath = baseOutDirPath
|
|
}
|
|
}
|
|
|
|
// Config is a configuration.
|
|
type Config struct {
|
|
// Required
|
|
PluginConfigs []*PluginConfig
|
|
}
|
|
|
|
// PluginConfig is a plugin configuration.
|
|
type PluginConfig struct {
|
|
// Required
|
|
Name string
|
|
// Required
|
|
Out string
|
|
// Optional
|
|
Opt string
|
|
// Optional
|
|
Path string
|
|
// Required
|
|
Strategy Strategy
|
|
}
|
|
|
|
// ReadConfig reads the configuration from the OS.
|
|
//
|
|
// This will first check if the override ends in .json or .yaml, if so,
|
|
// this reads the file at this path and uses it. Otherwise, this assumes this is configuration
|
|
// data in either JSON or YAML format, and unmarshals it.
|
|
//
|
|
// Only use in CLI tools.
|
|
func ReadConfig(fileOrData string) (*Config, error) {
|
|
return readConfig(fileOrData)
|
|
}
|
|
|
|
// ExternalConfigV1Beta1 is an external configuration.
|
|
//
|
|
// Only use outside of this package for testing.
|
|
type ExternalConfigV1Beta1 struct {
|
|
Version string `json:"version,omitempty" yaml:"version,omitempty"`
|
|
Plugins []ExternalPluginConfigV1Beta1 `json:"plugins,omitempty" yaml:"plugins,omitempty"`
|
|
}
|
|
|
|
// ExternalPluginConfigV1Beta1 is an external plugin configuration.
|
|
//
|
|
// Only use outside of this package for testing.
|
|
type ExternalPluginConfigV1Beta1 struct {
|
|
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
|
Out string `json:"out,omitempty" yaml:"out,omitempty"`
|
|
Opt interface{} `json:"opt,omitempty" yaml:"opt,omitempty"`
|
|
Path string `json:"path,omitempty" yaml:"path,omitempty"`
|
|
Strategy string `json:"strategy,omitempty" yaml:"strategy,omitempty"`
|
|
}
|
|
|
|
type externalConfigVersion struct {
|
|
Version string `json:"version,omitempty" yaml:"version,omitempty"`
|
|
}
|