mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-24 16:02:55 +08:00
fix(jetbrains): harden cloud history git remote lookup
This commit is contained in:
+18
-3
@@ -1,5 +1,9 @@
|
||||
package ai.kilocode.client.session.history
|
||||
|
||||
import java.io.File
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Resolves the origin remote URL for a given directory by running
|
||||
* `git remote get-url origin` as a subprocess.
|
||||
@@ -11,9 +15,20 @@ package ai.kilocode.client.session.history
|
||||
*/
|
||||
internal fun resolveGitRemoteUrl(dir: String): String? = runCatching {
|
||||
val proc = ProcessBuilder("git", "remote", "get-url", "origin")
|
||||
.directory(java.io.File(dir))
|
||||
.directory(File(dir))
|
||||
.redirectErrorStream(true)
|
||||
.start()
|
||||
val out = proc.inputStream.bufferedReader().readText().trim()
|
||||
val code = proc.waitFor()
|
||||
|
||||
val text = CompletableFuture.supplyAsync {
|
||||
proc.inputStream.bufferedReader().use { it.readText() }
|
||||
}
|
||||
val done = proc.waitFor(5, TimeUnit.SECONDS)
|
||||
if (!done) {
|
||||
proc.destroyForcibly()
|
||||
return@runCatching null
|
||||
}
|
||||
|
||||
val out = text.get(1, TimeUnit.SECONDS).trim()
|
||||
val code = proc.exitValue()
|
||||
if (code == 0 && out.isNotEmpty()) out else null
|
||||
}.getOrNull()
|
||||
|
||||
+19
-7
@@ -8,7 +8,11 @@ import ai.kilocode.rpc.dto.CloudSessionDto
|
||||
import ai.kilocode.rpc.dto.SessionDto
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class HistoryController(
|
||||
private val sessions: KiloSessionService,
|
||||
@@ -30,6 +34,10 @@ class HistoryController(
|
||||
var gitUrl: String? = null
|
||||
private set
|
||||
|
||||
@Volatile
|
||||
private var resolved = false
|
||||
private val lock = Mutex()
|
||||
|
||||
/** Whether to filter cloud history by the current repository. */
|
||||
var repoOnly: Boolean = false
|
||||
private set
|
||||
@@ -151,14 +159,18 @@ class HistoryController(
|
||||
* propagates state updates to EDT via [edt].
|
||||
*/
|
||||
private suspend fun resolveUrlIfNeeded(): String? {
|
||||
if (gitUrl != null) return gitUrl
|
||||
val url = kotlinx.coroutines.withContext(kotlinx.coroutines.Dispatchers.IO) {
|
||||
gitUrlProvider()
|
||||
if (resolved) return gitUrl
|
||||
return lock.withLock {
|
||||
if (resolved) return@withLock gitUrl
|
||||
val url = withContext(Dispatchers.IO) {
|
||||
gitUrlProvider()
|
||||
}
|
||||
// Write gitUrl directly (volatile) so it is visible before EDT callbacks fire.
|
||||
gitUrl = url
|
||||
resolved = true
|
||||
if (url != null) updateRepoOnly(true)
|
||||
url
|
||||
}
|
||||
// Write gitUrl directly (volatile) so it is visible before EDT callbacks fire.
|
||||
gitUrl = url
|
||||
if (url != null) updateRepoOnly(true)
|
||||
return url
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+18
@@ -27,6 +27,7 @@ import java.awt.Cursor
|
||||
import java.awt.event.KeyEvent
|
||||
import java.time.Instant
|
||||
import java.time.temporal.ChronoUnit
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.KeyStroke
|
||||
import javax.swing.event.ListDataEvent
|
||||
@@ -573,6 +574,23 @@ class HistoryControllerTest : BasePlatformTestCase() {
|
||||
assertNull(controller.gitUrl)
|
||||
}
|
||||
|
||||
fun `test cloud git url resolves once across overlapping reloads`() {
|
||||
rpc.cloud += cloud("cloud_1", "Cloud One")
|
||||
val calls = AtomicInteger()
|
||||
val controller = HistoryController(sessions, workspace, scope, gitUrlProvider = {
|
||||
calls.incrementAndGet()
|
||||
Thread.sleep(100)
|
||||
"git@github.com:test/repo.git"
|
||||
})
|
||||
|
||||
controller.reloadCloud()
|
||||
controller.reloadCloud()
|
||||
flush()
|
||||
|
||||
assertEquals(1, calls.get())
|
||||
assertEquals(2, rpc.cloudCalls.size)
|
||||
}
|
||||
|
||||
fun `test cloud load passes null when repo only disabled`() {
|
||||
rpc.cloud += cloud("cloud_1", "Cloud One")
|
||||
val url = "git@github.com:test/repo.git"
|
||||
|
||||
Reference in New Issue
Block a user