Commit Diff


commit - 72c6ec218af4da0b1abb8c7740c3e1fd3e9e1eef
commit + c20235ebf75e6aca44381b87eab66aa3efee8961
blob - 6a0bb32c7e8d756c4961baa329c7d45ae1176ee9
blob + b70c56e49fba205519e06536cdfe496117543d97
--- src/main/kotlin/dev/nezzontli/gotvcs/GotVcs.kt
+++ src/main/kotlin/dev/nezzontli/gotvcs/GotVcs.kt
@@ -28,7 +28,7 @@ class GotVcs(project: Project) : AbstractVcs(project, 
     private val checkinEnvironment = GotCheckinEnvironment(project, commandLine)
     private val rollbackEnvironment = GotRollbackEnvironment(project, commandLine)
     private val historyProvider = GotVcsHistoryProvider(project, commandLine)
-    private val updateEnvironment = GotUpdateEnvironment(commandLine)
+    private val updateEnvironment = GotUpdateEnvironment(project, commandLine)
     private val commitAndSendExecutor = GotCommitAndSendExecutor()
 
     override fun getDisplayName(): String = NAME
blob - bd5bbc7f7546b69cb7acdd9a86c59407e337e5a6
blob + 1bafc5551fbf24be1e68f4fbbe5554e781501dcb
--- src/main/kotlin/dev/nezzontli/gotvcs/checkin/GotCheckinEnvironment.kt
+++ src/main/kotlin/dev/nezzontli/gotvcs/checkin/GotCheckinEnvironment.kt
@@ -18,6 +18,7 @@ import com.intellij.openapi.vcs.checkin.CheckinEnviron
 import com.intellij.openapi.vfs.VfsUtilCore
 import com.intellij.openapi.vfs.VirtualFile
 import dev.nezzontli.gotvcs.cli.GotCommandLineWrapper
+import dev.nezzontli.gotvcs.log.GotVcsRefreshNotifier
 import dev.nezzontli.gotvcs.repo.GotRepositoryManager
 import java.io.File
 
@@ -103,9 +104,17 @@ class GotCheckinEnvironment(
                 exceptions.add(e)
             }
         }
+        notifyRootsChanged(filePaths)
         return exceptions
     }
 
+    /** Marks the affected roots dirty and pings the Log tab's refresher, if one is registered, so neither needs a manual reload after a commit. */
+    private fun notifyRootsChanged(filePaths: List<FilePath>) {
+        val vcsManager = ProjectLevelVcsManager.getInstance(project)
+        val notifier = project.getService(GotVcsRefreshNotifier::class.java)
+        filePaths.mapNotNull { vcsManager.getVcsRootFor(it) }.toSet().forEach { notifier.notifyChanged(it) }
+    }
+
     override fun scheduleMissingFileForDeletion(files: MutableList<out FilePath>): MutableList<VcsException> {
         val exceptions = mutableListOf<VcsException>()
         for ((workDir, paths) in groupByRoot(files)) {
blob - 773c61207552e102eb1c5d71fe27973802e17e87
blob + 45474126d5663012a92c7f3d2ca1c74445f182c6
--- src/main/kotlin/dev/nezzontli/gotvcs/log/GotVcsLogProvider.kt
+++ src/main/kotlin/dev/nezzontli/gotvcs/log/GotVcsLogProvider.kt
@@ -1,6 +1,7 @@
 package dev.nezzontli.gotvcs.log
 
 import com.intellij.openapi.Disposable
+import com.intellij.openapi.project.Project
 import com.intellij.openapi.vcs.VcsException
 import com.intellij.openapi.vcs.VcsKey
 import com.intellij.openapi.vcs.changes.Change
@@ -26,7 +27,10 @@ import java.util.concurrent.ConcurrentHashMap
  * index/cache beyond GotCommandLineWrapper's in-memory commit cache) -- same
  * philosophy as the rest of this plugin: no daemon, no persisted state.
  */
-class GotVcsLogProvider(private val commandLine: GotCommandLineWrapper = GotCommandLineWrapper()) : VcsLogProvider {
+class GotVcsLogProvider(
+    private val project: Project,
+    private val commandLine: GotCommandLineWrapper = GotCommandLineWrapper(),
+) : VcsLogProvider {
 
     override val supportedVcs: VcsKey = GotVcs.getKey()
 
@@ -146,7 +150,17 @@ class GotVcsLogProvider(private val commandLine: GotCo
     override fun subscribeToRootRefreshEvents(
         roots: Collection<VirtualFile>,
         refresher: com.intellij.vcs.log.VcsLogRefresher,
-    ): Disposable = Disposable { }
+    ): Disposable {
+        val notifier = project.getService(GotVcsRefreshNotifier::class.java)
+        for (root in roots) {
+            notifier.registerLogRefresher(root, refresher)
+        }
+        return Disposable {
+            for (root in roots) {
+                notifier.unregisterLogRefresher(root)
+            }
+        }
+    }
 
     private class SimpleLogData(
         override val refs: Set<VcsRef>,
blob - /dev/null
blob + e67c09b0f411fb64cf903b2a8d54775a1b43ec32 (mode 644)
--- /dev/null
+++ src/main/kotlin/dev/nezzontli/gotvcs/log/GotVcsRefreshNotifier.kt
@@ -0,0 +1,32 @@
+package dev.nezzontli.gotvcs.log
+
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager
+import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.vcs.log.VcsLogRefresher
+import java.util.concurrent.ConcurrentHashMap
+
+/**
+ * Central "something changed" signal for a got root: marks it dirty (so the
+ * Commit/Local Changes panel re-scans instead of waiting on the platform's
+ * own lazily-triggered refresh) and forwards to the Log tab's refresher, if
+ * one is currently registered (i.e. the Log tab is open). Called after any
+ * of our own commit/push/update operations.
+ */
+class GotVcsRefreshNotifier(private val project: Project) {
+
+    private val logRefreshers = ConcurrentHashMap<VirtualFile, VcsLogRefresher>()
+
+    fun registerLogRefresher(root: VirtualFile, refresher: VcsLogRefresher) {
+        logRefreshers[root] = refresher
+    }
+
+    fun unregisterLogRefresher(root: VirtualFile) {
+        logRefreshers.remove(root)
+    }
+
+    fun notifyChanged(root: VirtualFile) {
+        VcsDirtyScopeManager.getInstance(project).rootDirty(root)
+        logRefreshers[root]?.refresh(root)
+    }
+}
blob - 3c7dcf56b45ee99c4ea9fc2f8f27e69ca5c8a491
blob + a22b4e5424c02a7a344adc88416faf038386ebde
--- src/main/kotlin/dev/nezzontli/gotvcs/push/GotPusher.kt
+++ src/main/kotlin/dev/nezzontli/gotvcs/push/GotPusher.kt
@@ -7,6 +7,7 @@ import com.intellij.notification.NotificationGroupMana
 import com.intellij.notification.NotificationType
 import com.intellij.openapi.vcs.VcsException
 import dev.nezzontli.gotvcs.cli.GotCommandLineWrapper
+import dev.nezzontli.gotvcs.log.GotVcsRefreshNotifier
 import dev.nezzontli.gotvcs.repo.GotRepository
 import java.io.File
 
@@ -22,6 +23,9 @@ class GotPusher(private val commandLine: GotCommandLin
         for (repository in pushSpecs.keys) {
             try {
                 commandLine.send(File(repository.root.path))
+                // origin/<branch> moves after a successful send, which affects
+                // the Log tab's ref labels and outgoing-commits view.
+                repository.project.getService(GotVcsRefreshNotifier::class.java).notifyChanged(repository.root)
             } catch (e: VcsException) {
                 errors.add("${repository.root.path}: ${e.message}")
             }
blob - 14ac37f163aa2b2e48e77511a3e4a734425681ab
blob + 95606adcbec77102cc4b1f160e6a478a123c44df
--- src/main/kotlin/dev/nezzontli/gotvcs/update/GotUpdateEnvironment.kt
+++ src/main/kotlin/dev/nezzontli/gotvcs/update/GotUpdateEnvironment.kt
@@ -2,6 +2,7 @@ package dev.nezzontli.gotvcs.update
 
 import com.intellij.openapi.options.Configurable
 import com.intellij.openapi.progress.ProgressIndicator
+import com.intellij.openapi.project.Project
 import com.intellij.openapi.util.Ref
 import com.intellij.openapi.vcs.FilePath
 import com.intellij.openapi.vcs.VcsException
@@ -12,13 +13,17 @@ import com.intellij.openapi.vcs.update.UpdateSession
 import com.intellij.openapi.vcs.update.UpdatedFiles
 import dev.nezzontli.gotvcs.GotVcs
 import dev.nezzontli.gotvcs.cli.GotCommandLineWrapper
+import dev.nezzontli.gotvcs.log.GotVcsRefreshNotifier
 import java.io.File
 
 /**
  * "Update Project" runs `got fetch` (best-effort: got.conf may not have a
  * remote configured) followed by `got update` for each selected root.
  */
-class GotUpdateEnvironment(private val commandLine: GotCommandLineWrapper) : UpdateEnvironment {
+class GotUpdateEnvironment(
+    private val project: Project,
+    private val commandLine: GotCommandLineWrapper,
+) : UpdateEnvironment {
 
     override fun fillGroups(updatedFiles: UpdatedFiles) = Unit
 
@@ -29,9 +34,10 @@ class GotUpdateEnvironment(private val commandLine: Go
         context: Ref<SequentialUpdatesContext>,
     ): UpdateSession {
         val exceptions = mutableListOf<VcsException>()
-        val workDirs = contentRoots.map { File(it.path) }.distinct()
+        val roots = contentRoots.distinctBy { it.path }
 
-        for (workDir in workDirs) {
+        for (root in roots) {
+            val workDir = File(root.path)
             try {
                 commandLine.fetch(workDir)
             } catch (e: VcsException) {
@@ -56,6 +62,10 @@ class GotUpdateEnvironment(private val commandLine: Go
             } catch (e: VcsException) {
                 exceptions.add(e)
             }
+
+            // New commits may have just been pulled in by `got update`, so
+            // both the Commit panel and the Log tab need to know.
+            root.virtualFile?.let { project.getService(GotVcsRefreshNotifier::class.java).notifyChanged(it) }
         }
 
         return GotUpdateSession(exceptions)
blob - f5080061a1987c081204acc125599fc285fc261a
blob + 6243b948aadef67eb3a8dc52e5d173a621d11d28
--- src/main/resources/META-INF/plugin.xml
+++ src/main/resources/META-INF/plugin.xml
@@ -28,6 +28,7 @@
         <applicationConfigurable instance="dev.nezzontli.gotvcs.settings.GotConfigurable" displayName="got" parentId="vcs"/>
         <notificationGroup id="got" displayType="BALLOON"/>
         <projectService serviceImplementation="dev.nezzontli.gotvcs.repo.GotRepositoryManager"/>
+        <projectService serviceImplementation="dev.nezzontli.gotvcs.log.GotVcsRefreshNotifier"/>
         <statusBarWidgetFactory id="got.branch.widget"
                                  implementation="dev.nezzontli.gotvcs.repo.GotBranchWidget$Factory"
                                  order="after CodeStyleStatusBarWidget"/>