@@ -4,11 +4,13 @@ import (
44 "encoding/json"
55 "errors"
66 "fmt"
7+ "math"
78 "net/http"
89 "os"
910 "os/exec"
1011 "os/user"
1112 "runtime"
13+ "strconv"
1214 "strings"
1315)
1416
@@ -27,11 +29,24 @@ func Execute(programName string, args ...string) error {
2729 return cmd .Run ()
2830}
2931
30- func ExecuteHidden ( programName string , args ... string ) ( string , error ) {
32+ func ExecuteInDir ( workingDir , programName string , args ... string ) error {
3133 cmd := exec .Command (programName , args ... )
34+ cmd .Dir = workingDir
3235 cmd .Stdin = os .Stdin
3336 cmd .Stdout = os .Stdout
3437 cmd .Stderr = os .Stderr
38+ return cmd .Run ()
39+ }
40+
41+ func ExecuteHidden (programName string , args ... string ) (string , error ) {
42+ cmd := exec .Command (programName , args ... )
43+ out , err := cmd .CombinedOutput ()
44+ return string (out ), err
45+ }
46+
47+ func ExecuteInDirHidden (workingDir , programName string , args ... string ) (string , error ) {
48+ cmd := exec .Command (programName , args ... )
49+ cmd .Dir = workingDir
3550 out , err := cmd .CombinedOutput ()
3651 return string (out ), err
3752}
@@ -64,7 +79,7 @@ func OpenBrowser(url string) error {
6479 }
6580}
6681
67- func GithubTagFromMinorVersion (owner , repo , version string ) (string , error ) {
82+ func GithubTagFromVersion (owner , repo , version string ) (string , error ) {
6883 res , err := http .Get (fmt .Sprintf ("https://api.github.com/repos/%s/%s/tags" , owner , repo ))
6984 if err != nil {
7085 return "" , err
@@ -86,3 +101,90 @@ func GithubTagFromMinorVersion(owner, repo, version string) (string, error) {
86101 }
87102 return "" , ErrTagNotFound
88103}
104+
105+ func ClientVersionFromCGVersion (owner , repo , cgVersion string ) string {
106+ res , err := http .Get (fmt .Sprintf ("https://raw.githubusercontent.com/%s/%s/main/versions.json" , owner , repo ))
107+ if err != nil {
108+ fmt .Fprintf (os .Stderr , "\x1b [33mWARNING: Couldn't fetch versions.json. Using latest client library version.\n \x1b [0m" )
109+ return "latest"
110+ }
111+ defer res .Body .Close ()
112+
113+ var versions map [string ]string
114+ err = json .NewDecoder (res .Body ).Decode (& versions )
115+ if err != nil {
116+ fmt .Fprintf (os .Stderr , "\x1b [33mWARNING: Invalid versions.json. Using latest client library version.\n \x1b [0m" )
117+ return "latest"
118+ }
119+
120+ // check exact match
121+ if v , ok := versions [cgVersion ]; ok {
122+ return v
123+ }
124+
125+ parts := strings .Split (cgVersion , "." )
126+ if len (parts ) < 2 {
127+ fmt .Fprintf (os .Stderr , "\x1b [33mWARNING: Invalid versions.json. Using latest client library version.\n \x1b [0m" )
128+ return "latest"
129+ }
130+ major := parts [0 ]
131+
132+ // get all minor versions of the requested major version
133+ compatibleMinorVersions := make ([]int , 0 )
134+ for v := range versions {
135+ clientParts := strings .Split (v , "." )
136+ if len (clientParts ) < 2 {
137+ fmt .Fprintf (os .Stderr , "\x1b [33mWARNING: Invalid versions.json. Using latest client library version.\n \x1b [0m" )
138+ return "latest"
139+ }
140+ clientMajor := clientParts [0 ]
141+ if major == clientMajor {
142+ minor , err := strconv .Atoi (clientParts [1 ])
143+ if err != nil {
144+ fmt .Fprintf (os .Stderr , "\x1b [33mWARNING: Invalid versions.json. Using latest client library version.\n \x1b [0m" )
145+ return "latest"
146+ }
147+ compatibleMinorVersions = append (compatibleMinorVersions , minor )
148+ }
149+ }
150+ if len (compatibleMinorVersions ) == 0 {
151+ fmt .Fprintf (os .Stderr , "\x1b [33mWARNING: No compatible client library version found. Using latest client library version.\n \x1b [0m" )
152+ return "latest"
153+ }
154+
155+ minorStr := parts [1 ]
156+ minor , err := strconv .Atoi (minorStr )
157+ if err != nil {
158+ fmt .Fprintf (os .Stderr , "\x1b [33mWARNING: Invalid versions.json. Using latest client library version.\n \x1b [0m" )
159+ return "latest"
160+ }
161+
162+ // check closest minor version above requested
163+ closestMinor := - 1
164+ for _ , v := range compatibleMinorVersions {
165+ if v > minor && float64 (closestMinor - minor ) > float64 (v - minor ) {
166+ closestMinor = v
167+ }
168+ }
169+ if closestMinor >= 0 {
170+ v := fmt .Sprintf ("%s.%d" , major , minor )
171+ fmt .Fprintf (os .Stderr , "\x1b [33mWARNING: No exact version match found. Using client library version %s.\n \x1b [0m" , v )
172+ return v
173+ }
174+
175+ // check closest minor version below requested
176+ closestMinor = math .MaxInt
177+ for _ , v := range compatibleMinorVersions {
178+ if v < minor && float64 (minor - closestMinor ) > float64 (minor - v ) {
179+ closestMinor = v
180+ }
181+ }
182+ if closestMinor >= 0 {
183+ v := fmt .Sprintf ("%s.%d" , major , minor )
184+ fmt .Fprintf (os .Stderr , "\x1b [33mWARNING: No exact version match found. Using client library version %s.\n \x1b [0m" , v )
185+ return v
186+ }
187+
188+ fmt .Fprintf (os .Stderr , "\x1b [33mWARNING: No compatible client library version found. Using latest client library version.\n \x1b [0m" )
189+ return "latest"
190+ }
0 commit comments