commit 7ac4cd03f42b9a358ea84d07102683763f2235c4 from: ale date: Thu Jul 23 20:44:45 2026 UTC Corrige got fetch (SSH_AUTH_SOCK) y agrega logging al historial Reportado en vivo: 'Update Project' fallaba con 'Permission denied (publickey)' contra el remoto por SSH, pese a que el gpg-agent (soporte ssh, clave de YubiKey) funciona perfecto desde una shell normal. Confirmado: el proceso de IntelliJ SÍ tiene el SSH_AUTH_SOCK correcto (verificado leyendo /proc//environ), pero GeneralCommandLine usa por defecto un snapshot de entorno cacheado por la plataforma (EnvironmentUtil), no el entorno real del proceso -- ese snapshot no coincidía. Fix: se copia explícitamente SSH_AUTH_SOCK desde System.getenv() al entorno del subproceso antes de cada invocación. También: 'Show History' reportó 'Unknown error' sin rastro en el log de IntelliJ (ninguna excepción nuestra debería dar mensaje null). GotVcsHistoryProvider.createSessionFor() ahora loggea el stack trace completo de cualquier excepción no-VcsException y la envuelve con un mensaje no nulo, para poder diagnosticar la próxima vez que ocurra en vivo -- no se pudo reproducir el fallo original con 'got log' desde terminal (salió limpio), así que sigue pendiente de reproducir. commit - f2c271a1a7eb4bc7a6000c5b8ff246338d3ea016 commit + 7ac4cd03f42b9a358ea84d07102683763f2235c4 blob - 62c7c35916c9501165f4cadef5b9539a44a95a67 blob + 9bfb7a200eb39157f6f0baaab41e9a5b2a94bf8f --- src/main/kotlin/dev/nezzontli/gotvcs/GotCommandLineWrapper.kt +++ src/main/kotlin/dev/nezzontli/gotvcs/GotCommandLineWrapper.kt @@ -31,6 +31,13 @@ class GotCommandLineWrapper { val commandLine = GeneralCommandLine(binaryPath(), *args) .withWorkDirectory(workDir) .withCharset(StandardCharsets.UTF_8) + // GeneralCommandLine usa por defecto un snapshot de entorno cacheado + // por la plataforma (EnvironmentUtil), no el entorno real del proceso + // de IntelliJ. En este setup (gpg-agent con soporte ssh) ese snapshot + // puede no coincidir con SSH_AUTH_SOCK actual, y got/ssh fallan con + // "Permission denied (publickey)" aunque el agente esté vivo y con la + // clave cargada. Se fuerza explícitamente el valor real del proceso. + System.getenv("SSH_AUTH_SOCK")?.let { commandLine.environment["SSH_AUTH_SOCK"] = it } val output = try { ExecUtil.execAndGetOutput(commandLine) } catch (e: ExecutionException) { blob - 1a42e9637c573a2648e53d28c8aa02ff6bd317fc blob + 83adda8dcd5a20b3bedf901e8f6830cd6c475514 --- src/main/kotlin/dev/nezzontli/gotvcs/GotVcsHistoryProvider.kt +++ src/main/kotlin/dev/nezzontli/gotvcs/GotVcsHistoryProvider.kt @@ -12,6 +12,7 @@ import com.intellij.openapi.vcs.history.VcsDependentHi import com.intellij.openapi.vcs.history.VcsFileRevision import com.intellij.openapi.vcs.history.VcsHistoryProvider import com.intellij.openapi.vcs.history.VcsHistorySession +import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.vfs.VfsUtilCore import com.intellij.util.ui.ColumnInfo import java.io.File @@ -21,6 +22,8 @@ class GotVcsHistoryProvider( private val commandLine: GotCommandLineWrapper, ) : VcsHistoryProvider { + private val LOG = Logger.getInstance(GotVcsHistoryProvider::class.java) + override fun getUICustomization(session: VcsHistorySession, forShortcutRegistration: javax.swing.JComponent) = VcsDependentHistoryComponents.createOnlyColumns(emptyArray>()) @@ -38,16 +41,26 @@ class GotVcsHistoryProvider( @Throws(VcsException::class) override fun createSessionFor(filePath: FilePath): VcsHistorySession { - val vcsRoot = ProjectLevelVcsManager.getInstance(project).getVcsRootFor(filePath) - ?: throw VcsException("$filePath no pertenece a ningún work tree got") - val workDir = File(vcsRoot.path) - val relativePath = VfsUtilCore.getRelativePath(filePath.virtualFile ?: vcsRoot, vcsRoot) - ?: throw VcsException("No se pudo resolver la ruta relativa de $filePath en $workDir") + try { + val vcsRoot = ProjectLevelVcsManager.getInstance(project).getVcsRootFor(filePath) + ?: throw VcsException("$filePath no pertenece a ningún work tree got") + val workDir = File(vcsRoot.path) + val relativePath = VfsUtilCore.getRelativePath(filePath.virtualFile ?: vcsRoot, vcsRoot) + ?: throw VcsException("No se pudo resolver la ruta relativa de $filePath en $workDir") - val entries = commandLine.log(workDir, relativePath.ifEmpty { null }) - val revisions: List = entries.map { GotFileRevision(workDir, relativePath, commandLine, it) } - val baseRevision = GotRevisionNumber(commandLine.baseCommit(workDir)) - return GotVcsHistorySession(revisions, baseRevision) + val entries = commandLine.log(workDir, relativePath.ifEmpty { null }) + val revisions: List = entries.map { GotFileRevision(workDir, relativePath, commandLine, it) } + val baseRevision = GotRevisionNumber(commandLine.baseCommit(workDir)) + return GotVcsHistorySession(revisions, baseRevision) + } catch (e: VcsException) { + throw e + } catch (e: Exception) { + // El panel de historial solo muestra e.message (a veces como + // "Unknown error" si es null); loggeamos el stack completo para + // poder diagnosticar fallos que no sean VcsException nuestras. + LOG.warn("Fallo al construir el historial got para $filePath", e) + throw VcsException("${e.javaClass.simpleName}: ${e.message ?: "sin mensaje"}", e) + } } @Throws(VcsException::class)