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 }