Browse Source

Feat: vprotogen adds version detector (#819)

* Feat: vprotogen adds version detector to block generation code from old protobuf version
* Chore: update .gitignore
Loyalsoldier 4 years ago
parent
commit
389ff73a26
2 changed files with 78 additions and 0 deletions
  1. 1 0
      .gitignore
  2. 77 0
      infra/vprotogen/main.go

+ 1 - 0
.gitignore

@@ -22,3 +22,4 @@ v2ray
 v2ctl
 mockgen
 vprotogen
+!infra/vprotogen/

+ 77 - 0
infra/vprotogen/main.go

@@ -3,11 +3,15 @@ package main
 import (
 	"fmt"
 	"go/build"
+	"io"
 	"io/ioutil"
+	"net/http"
 	"os"
 	"os/exec"
 	"path/filepath"
+	"regexp"
 	"runtime"
+	"strconv"
 	"strings"
 )
 
@@ -77,7 +81,62 @@ func GetGOBIN() string {
 	return GOBIN
 }
 
+func getProjectProtocVersion(url string) (string, error) {
+	resp, err := http.Get(url)
+	if err != nil {
+		return "", fmt.Errorf("can not get the version of protobuf used in V2Ray project")
+	}
+	defer resp.Body.Close()
+	body, err := io.ReadAll(resp.Body)
+	if err != nil {
+		return "", fmt.Errorf("can not read from body")
+	}
+	versionRegexp := regexp.MustCompile(`\/\/\s*protoc\s*v(\d+\.\d+\.\d+)`)
+	matched := versionRegexp.FindStringSubmatch(string(body))
+	return matched[1], nil
+}
+
+func getInstalledProtocVersion(protocPath string) (string, error) {
+	cmd := exec.Command(protocPath, "--version")
+	cmd.Env = append(cmd.Env, os.Environ()...)
+	output, cmdErr := cmd.CombinedOutput()
+	if cmdErr != nil {
+		return "", cmdErr
+	}
+	versionRegexp := regexp.MustCompile(`protoc\s*(\d+\.\d+\.\d+)`)
+	matched := versionRegexp.FindStringSubmatch(string(output))
+	return matched[1], nil
+}
+
+func parseVersion(s string, width int) int64 {
+	strList := strings.Split(s, ".")
+	format := fmt.Sprintf("%%s%%0%ds", width)
+	v := ""
+	for _, value := range strList {
+		v = fmt.Sprintf(format, v, value)
+	}
+	var result int64
+	var err error
+	if result, err = strconv.ParseInt(v, 10, 64); err != nil {
+		return 0
+	}
+	return result
+}
+
+func needToUpdate(targetedVersion, installedVersion string) bool {
+	vt := parseVersion(targetedVersion, 4)
+	vi := parseVersion(installedVersion, 4)
+
+	return vt > vi
+}
+
 func main() {
+	targetedVersion, err := getProjectProtocVersion("https://raw.githubusercontent.com/v2fly/v2ray-core/HEAD/config.pb.go")
+	if err != nil {
+		fmt.Println(err)
+		os.Exit(1)
+	}
+
 	pwd, wdErr := os.Getwd()
 	if wdErr != nil {
 		fmt.Println("Can not get current working directory.")
@@ -103,6 +162,24 @@ func main() {
 		protoc = path
 	}
 
+	installedVersion, err := getInstalledProtocVersion(protoc)
+	if err != nil {
+		fmt.Println(err)
+		os.Exit(1)
+	}
+
+	if needToUpdate(targetedVersion, installedVersion) {
+		fmt.Printf(`
+You are using an old protobuf version. Please update to v%s or later.
+Download it from https://github.com/protocolbuffers/protobuf/releases
+
+    * Protobuf version used in V2Ray project: v%s
+    * Protobuf version you have installed: v%s
+
+`, targetedVersion, targetedVersion, installedVersion)
+		os.Exit(1)
+	}
+
 	protoFilesMap := make(map[string][]string)
 	walkErr := filepath.Walk("./", func(path string, info os.FileInfo, err error) error {
 		if err != nil {