blob: 262e7ea166ae448cefc9e7ccbe90623fcc313851 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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 bufpluginexec
import (
"errors"
"fmt"
"strconv"
"strings"
)
import (
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/pluginpb"
)
func newVersion(major int32, minor int32, patch int32, suffix string) *pluginpb.Version {
version := &pluginpb.Version{
Major: proto.Int32(major),
Minor: proto.Int32(minor),
Patch: proto.Int32(patch),
}
if suffix != "" {
version.Suffix = proto.String(suffix)
}
return version
}
func parseVersionForCLIVersion(value string) (_ *pluginpb.Version, retErr error) {
defer func() {
if retErr != nil {
retErr = fmt.Errorf("cannot parse protoc version %q: %w", value, retErr)
}
}()
// protoc always starts with "libprotoc "
value = strings.TrimPrefix(value, "libprotoc ")
split := strings.Split(value, ".")
if n := len(split); n != 2 && n != 3 {
return nil, fmt.Errorf("%d components split by '.'", n)
}
major, err := strconv.ParseInt(split[0], 10, 32)
if err != nil {
return nil, err
}
var suffix string
restSplit := strings.SplitN(split[len(split)-1], "-", 2)
lastNumber, err := strconv.ParseInt(restSplit[0], 10, 32)
if err != nil {
return nil, err
}
switch len(restSplit) {
case 1:
case 2:
suffix = restSplit[1]
default:
return nil, errors.New("more than two patch components split by '-'")
}
var minor int64
var patch int64
switch len(split) {
case 2:
minor = lastNumber
case 3:
minor, err = strconv.ParseInt(split[1], 10, 32)
if err != nil {
return nil, err
}
patch = lastNumber
}
return newVersion(int32(major), int32(minor), int32(patch), suffix), nil
}
func versionString(version *pluginpb.Version) string {
var value string
if version.GetMajor() <= 3 || version.GetPatch() != 0 {
value = fmt.Sprintf("%d.%d.%d", version.GetMajor(), version.GetMinor(), version.GetPatch())
} else {
value = fmt.Sprintf("%d.%d", version.GetMajor(), version.GetMinor())
}
if version.Suffix != nil {
value = value + "-" + version.GetSuffix()
}
return value
}
// Should I set the --experimental_allow_proto3_optional flag?
func getSetExperimentalAllowProto3OptionalFlag(version *pluginpb.Version) bool {
if version.GetSuffix() == "buf" {
return false
}
if version.GetMajor() != 3 {
return false
}
return version.GetMinor() > 11 && version.GetMinor() < 15
}
// Should I notify that I am OK with the proto3 optional feature?
func getFeatureProto3OptionalSupported(version *pluginpb.Version) bool {
if version.GetSuffix() == "buf" {
return true
}
if version.GetMajor() < 3 {
return false
}
if version.GetMajor() == 3 {
return version.GetMinor() > 11
}
// version.GetMajor() > 3
return true
}
// Is kotlin supported as a builtin plugin?
func getKotlinSupportedAsBuiltin(version *pluginpb.Version) bool {
if version.GetSuffix() == "buf" {
return true
}
if version.GetMajor() < 3 {
return false
}
if version.GetMajor() == 3 {
return version.GetMinor() > 16
}
// version.GetMajor() > 3
return true
}
// Is js supported as a builtin plugin?
func getJSSupportedAsBuiltin(version *pluginpb.Version) bool {
if version.GetSuffix() == "buf" {
return true
}
if version.GetMajor() < 3 {
return false
}
if version.GetMajor() == 3 {
// v21 and above of protoc still returns "3.MAJOR.Z" for version
return version.GetMinor() < 21
}
// version.GetMajor() > 3
// This will catch if they ever change protoc's returned version
// to the proper major version
return false
}