6
6
"os"
7
7
"path/filepath"
8
8
"regexp"
9
+ "slices"
9
10
"strings"
10
11
11
12
"github.com/tarantool/tt/cli/install"
@@ -17,12 +18,6 @@ import (
17
18
)
18
19
19
20
const (
20
- progRegexp = "(?P<prog>" +
21
- search .ProgramTt + "|" +
22
- search .ProgramCe + "|" +
23
- search .ProgramEe + ")"
24
- verRegexp = "(?P<ver>.*)"
25
-
26
21
MajorMinorPatchRegexp = `^[0-9]+\.[0-9]+\.[0-9]+`
27
22
)
28
23
@@ -180,132 +175,88 @@ func getAllTtVersionFormats(programName, ttVersion string) ([]string, error) {
180
175
181
176
// getDefault returns a default version of an installed program.
182
177
func getDefault (program , dir string ) (string , error ) {
183
- var ver string
184
-
185
- re := regexp .MustCompile (
186
- "^" + program + version .FsSeparator + verRegexp + "$" ,
187
- )
188
-
189
- installedPrograms , err := os .ReadDir (dir )
178
+ versions , err := GetAvailableVersions (program , dir )
190
179
if err != nil {
191
180
return "" , err
192
181
}
193
-
194
- for _ , file := range installedPrograms {
195
- matches := util .FindNamedMatches (re , file .Name ())
196
- if ver != "" {
197
- return "" , fmt .Errorf ("%s has more than one installed version, " +
198
- "please specify the version to uninstall" , program )
199
- } else {
200
- ver = matches ["ver" ]
201
- }
202
- }
203
-
204
- if ver == "" {
182
+ if len (versions ) == 0 {
205
183
return "" , fmt .Errorf ("%s has no installed version" , program )
206
184
}
207
- return ver , nil
185
+ if len (versions ) > 1 {
186
+ return "" , fmt .Errorf ("%s has more than one installed version, " +
187
+ "please specify the version to uninstall" , program )
188
+ }
189
+ return versions [0 ], nil
208
190
}
209
191
210
192
// GetAvailableVersions returns a list of the program's versions installed into
211
193
// the 'dir' directory.
212
- func GetAvailableVersions (program string , dir string ) []string {
213
- if dir == "" {
214
- return nil
194
+ func GetAvailableVersions (program string , dir string ) ( []string , error ) {
195
+ if ! util . IsDir ( dir ) {
196
+ return nil , fmt . Errorf ( "%q is missing or not a directory" , dir )
215
197
}
216
198
217
199
versionPrefix := filepath .Join (dir , program + version .FsSeparator )
218
200
219
201
programFiles , err := filepath .Glob (versionPrefix + "*" )
220
202
if err != nil {
221
- return nil
203
+ return nil , err
222
204
}
223
205
224
206
versions := []string {}
225
207
for _ , file := range programFiles {
226
208
versions = append (versions , file [len (versionPrefix ):])
227
209
}
228
210
229
- return versions
211
+ return versions , nil
230
212
}
231
213
232
214
// searchLatestVersion searches for the latest installed version of the program.
233
- func searchLatestVersion (linkName , binDst , headerDst string ) (string , error ) {
234
- var programsToSearch []string
235
- if linkName == "tarantool" {
236
- programsToSearch = []string {search .ProgramCe , search .ProgramEe }
237
- } else {
238
- programsToSearch = []string {linkName }
215
+ func searchLatestVersion (program , binDst , headerDst string ) (string , error ) {
216
+ binVersions , err := GetAvailableVersions (program , binDst )
217
+ if err != nil {
218
+ return "" , err
239
219
}
240
220
241
- programRegex := regexp .MustCompile (
242
- "^" + progRegexp + version .FsSeparator + verRegexp + "$" ,
243
- )
244
-
245
- binaries , err := os .ReadDir (binDst )
221
+ headerVersions , err := GetAvailableVersions (program , headerDst )
246
222
if err != nil {
247
223
return "" , err
248
224
}
249
225
250
- latestVersionInfo := version.Version {}
251
- latestVersion := ""
252
- hashFound := false
253
- latestHash := ""
254
-
255
- for _ , binary := range binaries {
256
- if binary .IsDir () {
257
- continue
258
- }
259
- binaryName := binary .Name ()
260
- matches := util .FindNamedMatches (programRegex , binaryName )
226
+ binPrefix := filepath .Join (binDst , program + version .FsSeparator )
261
227
262
- // Need to match for the program and version.
263
- if len (matches ) != 2 {
264
- log .Debugf ("%q skipped: unexpected format" , binaryName )
228
+ // Find intersection and convert to version.Version
229
+ versions := []version.Version {}
230
+ for _ , binVersion := range binVersions {
231
+ if util .IsDir (binPrefix + binVersion ) {
265
232
continue
266
233
}
267
234
268
- programName := matches ["prog" ]
269
- // Need to find the program in the list of suitable.
270
- if util .Find (programsToSearch , programName ) == - 1 {
271
- continue
272
- }
273
- isRightFormat , _ := util .IsValidCommitHash (matches ["ver" ])
274
-
275
- if isRightFormat {
276
- if hashFound {
235
+ if slices .Contains (headerVersions , binVersion ) {
236
+ ver , err := version .Parse (binVersion )
237
+ if err != nil {
277
238
continue
278
239
}
279
- if strings .Contains (programName , "tarantool" ) {
280
- // Check for headers.
281
- if _ , err := os .Stat (filepath .Join (headerDst , binaryName )); os .IsNotExist (err ) {
282
- continue
283
- }
284
- }
285
- hashFound = true
286
- latestHash = binaryName
287
- continue
288
- }
289
- ver , err := version .Parse (matches ["ver" ])
290
- if err != nil {
291
- continue
292
- }
293
- if strings .Contains (programName , "tarantool" ) {
294
- // Check for headers.
295
- if _ , err := os .Stat (filepath .Join (headerDst , binaryName )); os .IsNotExist (err ) {
296
- continue
297
- }
298
- }
299
- // Update latest version.
300
- if latestVersion == "" || version .IsLess (latestVersionInfo , ver ) {
301
- latestVersionInfo = ver
302
- latestVersion = binaryName
240
+ versions = append (versions , ver )
303
241
}
304
242
}
305
- if latestVersion != "" {
306
- return latestVersion , nil
243
+
244
+ if len (versions ) == 0 {
245
+ return "" , nil
307
246
}
308
- return latestHash , nil
247
+
248
+ latestVersion := slices .MaxFunc (versions , func (a , b version.Version ) int {
249
+ if a .Str == b .Str {
250
+ return 0
251
+ }
252
+ isCommitHash , _ := util .IsValidCommitHash (a .Str )
253
+ if isCommitHash || version .IsLess (a , b ) {
254
+ return - 1
255
+ }
256
+ return 1
257
+ })
258
+
259
+ return program + version .FsSeparator + latestVersion .Str , nil
309
260
}
310
261
311
262
// switchProgramToLatestVersion switches the active version of the program to the latest installed.
@@ -315,7 +266,7 @@ func switchProgramToLatestVersion(program, binDst, headerDst string) error {
315
266
linkName = "tarantool"
316
267
}
317
268
318
- progToSwitch , err := searchLatestVersion (linkName , binDst , headerDst )
269
+ progToSwitch , err := searchLatestVersion (program , binDst , headerDst )
319
270
if err != nil {
320
271
return err
321
272
}
0 commit comments