github.com/quickfeed/quickfeed@v0.0.0-20240507093252-ed8ca812a09c/cmd/vercheck/main.go (about)

     1  package main
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"os"
     7  	"regexp"
     8  	"sort"
     9  	"strings"
    10  
    11  	"github.com/quickfeed/quickfeed/kit/sh"
    12  )
    13  
    14  const (
    15  	pbgo   = "qf/quickfeed.pb.go"
    16  	grpcpb = "qf/qfconnect/quickfeed.connect.go"
    17  )
    18  
    19  func main() {
    20  	protoc := regexp.MustCompile(`^\/\/.*(protoc)\s+(.*)$`)
    21  	// protoc := regexp.MustCompile(`^\/\/.*(protoc)\s+v(.*)$`)
    22  	genGo := regexp.MustCompile(`^\/\/.*(protoc-gen-go)\s+v(.*)$`)
    23  	genGoGrpc := regexp.MustCompile(`^\/\/.*(protoc-gen-go-grpc)\s+v(.*)$`)
    24  
    25  	needUpdate := false
    26  	for re, file := range map[*regexp.Regexp]string{
    27  		protoc:    pbgo,
    28  		genGo:     pbgo,
    29  		genGoGrpc: grpcpb,
    30  	} {
    31  		tool, codeVer := scan(file, re)
    32  		toolVer := toolVersion(tool)
    33  		needUpdate = needUpdate || checkVersions(tool, toolVer, codeVer)
    34  	}
    35  	if needUpdate {
    36  		os.Exit(1)
    37  	}
    38  }
    39  
    40  // checkVersions returns true if the installed tool must be updated.
    41  func checkVersions(tool, toolVer, codeVer string) bool {
    42  	if toolVer != codeVer && sort.StringsAreSorted([]string{toolVer, codeVer}) {
    43  		fmt.Printf("Installed %q version %v is older than generated code version %v\n", tool, toolVer, codeVer)
    44  		return true
    45  	}
    46  	return false
    47  }
    48  
    49  // toolVersion returns the given tool's version.
    50  func toolVersion(tool string) string {
    51  	s, stdErr, _ := sh.OutputErr(tool + " --version")
    52  	stdErr = strings.TrimSpace(stdErr)
    53  	for _, errMsg := range []string{
    54  		`Missing value for flag: --version`,
    55  		`unknown argument "--version"`,
    56  		`flag provided but not defined: -version`,
    57  	} {
    58  		if strings.Contains(stdErr, errMsg) {
    59  			fmt.Printf("Installed %q version is too old.\n", tool)
    60  			return "?"
    61  		}
    62  	}
    63  	i := strings.LastIndex(s, " ")
    64  	s = s[i+1:]
    65  	if strings.HasPrefix(s, "v") {
    66  		// annoyingly some tools use v and others don't
    67  		return s[1:]
    68  	}
    69  	return s
    70  }
    71  
    72  // scan returns the tool (matching the regex) and version used to generated the given file.
    73  func scan(file string, re *regexp.Regexp) (string, string) {
    74  	f, err := os.Open(file)
    75  	check(err)
    76  	defer func() {
    77  		check(f.Close())
    78  	}()
    79  	scanner := bufio.NewScanner(f)
    80  	for scanner.Scan() {
    81  		line := scanner.Text()
    82  		if re.MatchString(line) {
    83  			s := re.ReplaceAllString(line, "$1:$2")
    84  			i := strings.Index(s, ":")
    85  			return s[:i], s[i+1:] // tool and version
    86  		}
    87  	}
    88  	check(scanner.Err())
    89  	return "", ""
    90  }
    91  
    92  func check(err error) {
    93  	if err != nil {
    94  		fmt.Println(err)
    95  	}
    96  }