Skip to content

Commit 98dc126

Browse files
committed
impl: UTs for URI handling and a couple of other optimizations
1 parent ce3f67b commit 98dc126

File tree

3 files changed

+174
-243
lines changed

3 files changed

+174
-243
lines changed

src/main/kotlin/com/coder/toolbox/feed/IdeFeedManager.kt

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -208,28 +208,6 @@ class IdeFeedManager(
208208
* This method filters the loaded IDEs by product code and type, optionally
209209
* filtering by available builds, then returns the IDE with the highest build.
210210
*
211-
* Build comparison is done lexicographically (string comparison).
212-
*
213-
* @param query The query criteria specifying product code, type, and optional available builds
214-
* @return The IDE with the highest build matching the criteria, or null if no match found
215-
*/
216-
suspend fun findBestMatch(query: IdeQuery): Ide? {
217-
val ides = loadIdes()
218-
219-
return ides
220-
.filter { it.code == query.productCode }
221-
.filter { it.type == query.type }
222-
.let { filtered ->
223-
filtered.filter { it.build in query.availableBuilds }
224-
}
225-
.maxByOrNull { it.build }
226-
}
227-
228-
/**
229-
* Convenience method to find the best matching IDE.
230-
*
231-
* This is a shorthand for creating an IdeQuery and calling findBestMatch(query).
232-
*
233211
* @param productCode The IntelliJ product code (e.g., "RR" for RustRover)
234212
* @param type The type of IDE release (RELEASE or EAP)
235213
* @param availableBuilds List of acceptable builds to filter by
@@ -239,9 +217,15 @@ class IdeFeedManager(
239217
productCode: String,
240218
type: IdeType,
241219
availableBuilds: List<String>
242-
): Ide? = findBestMatch(
243-
IdeQuery(productCode, type, availableBuilds)
244-
)
220+
): Ide? {
221+
val ides = loadIdes()
222+
223+
return ides
224+
.filter { it.code == productCode }
225+
.filter { it.type == type }
226+
.filter { it.build in availableBuilds }
227+
.maxByOrNull { it.build }
228+
}
245229

246230
companion object {
247231
private const val RELEASE_CACHE_FILE = "release.json"

src/main/kotlin/com/coder/toolbox/util/CoderProtocolHandler.kt

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -257,20 +257,19 @@ open class CoderProtocolHandler(
257257
buildNumberHint: String,
258258
environmentId: String
259259
): String? {
260-
val selectedIdeVersion = resolveIdeIdentifier(environmentId, productCode, buildNumberHint) ?: return null
260+
val selectedIde = resolveIdeIdentifier(environmentId, productCode, buildNumberHint) ?: return null
261261
val installedIdeVersions = context.remoteIdeOrchestrator.getInstalledRemoteTools(environmentId, productCode)
262262

263-
if (installedIdeVersions.contains(selectedIdeVersion)) {
264-
context.logger.info("$selectedIdeVersion is already installed on $environmentId")
265-
return selectedIdeVersion
263+
if (installedIdeVersions.contains(selectedIde)) {
264+
context.logger.info("$selectedIde is already installed on $environmentId")
265+
return selectedIde
266266
}
267267

268-
val selectedIde = "$productCode-$selectedIdeVersion"
269268
context.logger.info("Installing $selectedIde on $environmentId...")
270269
context.remoteIdeOrchestrator.installRemoteTool(environmentId, selectedIde)
271270

272271
if (context.remoteIdeOrchestrator.waitForIdeToBeInstalled(environmentId, selectedIde)) {
273-
context.logger.info("Successfully installed $selectedIdeVersion on $environmentId.")
272+
context.logger.info("Successfully installed $selectedIde on $environmentId.")
274273
return selectedIde
275274
} else {
276275
context.ui.showSnackbar(
@@ -293,10 +292,12 @@ open class CoderProtocolHandler(
293292
buildNumberHint: String
294293
): String? {
295294
val availableBuilds = context.remoteIdeOrchestrator.getAvailableRemoteTools(environmentId, productCode)
295+
.map { it.substringAfter("$productCode-") }
296+
val installed = context.remoteIdeOrchestrator.getInstalledRemoteTools(environmentId, productCode)
297+
.map { it.substringAfter("$productCode-") }
296298

297299
when (buildNumberHint) {
298300
"latest_eap" -> {
299-
// Use IdeFeedManager to find best EAP match from available builds
300301
val bestEap = ideFeedManager.findBestMatch(
301302
productCode,
302303
IdeType.EAP,
@@ -306,14 +307,14 @@ open class CoderProtocolHandler(
306307
return if (bestEap != null) {
307308
bestEap.build
308309
} else {
309-
// Fallback to latest available if valid
310310
if (availableBuilds.isEmpty()) {
311311
context.logAndShowError(
312312
CAN_T_HANDLE_URI_TITLE,
313-
"$productCode is not available on $environmentId"
313+
"Can't launch EAP for $productCode because no version is available on $environmentId"
314314
)
315315
return null
316316
}
317+
// Fallback to max available
317318
val fallback = availableBuilds.maxBy { it }
318319
context.logger.info("No EAP found for $productCode, falling back to latest available: $fallback")
319320
fallback
@@ -324,17 +325,15 @@ open class CoderProtocolHandler(
324325
val bestRelease = ideFeedManager.findBestMatch(
325326
productCode,
326327
IdeType.RELEASE,
327-
availableBuilds
328-
)
328+
availableBuilds.map { it.substringAfter("$productCode-") })
329329

330330
return if (bestRelease != null) {
331331
bestRelease.build
332332
} else {
333-
// Fallback to latest available if valid
334333
if (availableBuilds.isEmpty()) {
335334
context.logAndShowError(
336335
CAN_T_HANDLE_URI_TITLE,
337-
"$productCode is not available on $environmentId"
336+
"Can't launch Release for $productCode because no version is available on $environmentId"
338337
)
339338
return null
340339
}
@@ -345,26 +344,40 @@ open class CoderProtocolHandler(
345344
}
346345

347346
"latest_installed" -> {
348-
val installed = context.remoteIdeOrchestrator.getInstalledRemoteTools(environmentId, productCode)
349347
if (installed.isNotEmpty()) {
350348
return installed.maxBy { it }
351349
}
352-
// Fallback to latest available if valid
353350
if (availableBuilds.isEmpty()) {
354-
context.logAndShowError(CAN_T_HANDLE_URI_TITLE, "$productCode is not available on $environmentId")
351+
context.logAndShowError(
352+
CAN_T_HANDLE_URI_TITLE,
353+
"Can't launch latest installed version for $productCode because there is no version installed nor available for install on $environmentId"
354+
)
355355
return null
356356
}
357+
// Fallback to latest available if valid
357358
val fallback = availableBuilds.maxBy { it }
358359
context.logger.info("No installed IDE found, falling back to latest available: $fallback")
359360
return fallback
360361
}
361362

362363
else -> {
363-
// Specific build number
364-
// Check if exact match exists in available or installed (implicitly handled by install check later)
365-
// Often the input buildNumber might be just "241" or "241.1234", but full build version is in the form of 241.1234.234"
364+
// Specific build number. First check it in the installed list of builds
365+
// then in the available list of builds
366+
val installedMatch = installed.firstOrNull { it.contains(buildNumberHint) }
367+
if (installedMatch != null) {
368+
return installedMatch
369+
}
370+
val availableMatch = availableBuilds.filter { it.contains(buildNumberHint) }.maxByOrNull { it }
371+
if (availableMatch != null) {
372+
return availableMatch
373+
} else {
374+
context.logAndShowError(
375+
CAN_T_HANDLE_URI_TITLE,
376+
"Can't launch $productCode-$buildNumberHint because there is no matching version installed nor available for install on $environmentId"
377+
)
378+
return null
379+
}
366380

367-
return availableBuilds.filter { it.contains(buildNumberHint) }.maxByOrNull { it }
368381
}
369382
}
370383
}

0 commit comments

Comments
 (0)