don't reload all scheme managers blindly

This commit is contained in:
Vladimir Krivosheev
2016-12-23 08:24:26 +01:00
parent 0ed81175f1
commit 455795f465
3 changed files with 70 additions and 15 deletions
@@ -20,11 +20,16 @@ import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.util.AtomicClearableLazyValue
import com.intellij.util.containers.mapSmartNotNull
import com.intellij.util.io.exists
import gnu.trove.THashSet
import org.eclipse.jgit.diff.DiffEntry
import org.eclipse.jgit.diff.DiffFormatter
import org.eclipse.jgit.lib.Repository
import org.eclipse.jgit.storage.file.FileRepositoryBuilder
import org.eclipse.jgit.util.io.DisabledOutputStream
import org.jetbrains.settingsRepository.git.GitRepositoryClientImpl
import org.jetbrains.settingsRepository.git.Pull
import org.jetbrains.settingsRepository.git.upstream
import org.jetbrains.settingsRepository.git.use
import java.nio.file.Path
class ReadOnlySourceManager(private val settings: IcsSettings, val rootDir: Path) {
@@ -62,16 +67,50 @@ class ReadOnlySourceManager(private val settings: IcsSettings, val rootDir: Path
repositoryList.drop()
}
fun update(indicator: ProgressIndicator? = null): Boolean {
var isChanged = false
fun update(indicator: ProgressIndicator? = null): Set<String>? {
var changedRootDirs: MutableSet<String>? = null
fun addChangedPath(path: String?) {
if (path == null || path == DiffEntry.DEV_NULL) {
return
}
var firstSlash = path.indexOf('/')
if (firstSlash < 0) {
// path must use only /, but who knows
firstSlash = path.indexOf('\\')
}
if (firstSlash > 0) {
if (changedRootDirs == null) {
changedRootDirs = THashSet()
}
changedRootDirs!!.add(path.substring(0, firstSlash))
}
}
for (repo in repositories) {
indicator?.checkCanceled()
LOG.debug { "Pull changes from read-only repo ${repo.upstream}" }
if (Pull(GitRepositoryClientImpl(repo, icsManager.credentialsStore), indicator).fetch() != null) {
isChanged = true
}
Pull(GitRepositoryClientImpl(repo, icsManager.credentialsStore), indicator).fetch(refUpdateProcessor = { refUpdate ->
val diffFormatter = DiffFormatter(DisabledOutputStream.INSTANCE)
diffFormatter.setRepository(repo)
diffFormatter.use {
val result = diffFormatter.scan(refUpdate.oldObjectId, refUpdate.newObjectId)
for (e in result) {
if (e.changeType == DiffEntry.ChangeType.DELETE) {
addChangedPath(e.oldPath)
}
else {
addChangedPath(e.oldPath)
addChangedPath(e.newPath)
}
}
}
})
}
return isChanged
return changedRootDirs
}
}
+4 -1
View File
@@ -40,6 +40,7 @@ import org.eclipse.jgit.revwalk.RevWalk
import org.eclipse.jgit.revwalk.RevWalkUtils
import org.eclipse.jgit.transport.CredentialsProvider
import org.eclipse.jgit.transport.RemoteConfig
import org.eclipse.jgit.transport.TrackingRefUpdate
import org.eclipse.jgit.treewalk.FileTreeIterator
import org.jetbrains.settingsRepository.*
import java.io.IOException
@@ -87,7 +88,7 @@ open internal class Pull(val manager: GitRepositoryClient, val indicator: Progre
}
}
fun fetch(prevRefUpdateResult: RefUpdate.Result? = null): Ref? {
fun fetch(prevRefUpdateResult: RefUpdate.Result? = null, refUpdateProcessor: ((TrackingRefUpdate) -> Unit)? = null): Ref? {
indicator?.checkCanceled()
val fetchResult = repository.fetch(remoteConfig, manager.credentialsProvider, indicator.asProgressMonitor()) ?: return null
@@ -128,6 +129,8 @@ open internal class Pull(val manager: GitRepositoryClient, val indicator: Progre
if (!hasChanges) {
hasChanges = refUpdateResult != RefUpdate.Result.NO_CHANGE
}
refUpdateProcessor?.invoke(refUpdate)
}
if (!hasChanges) {
+21 -8
View File
@@ -22,6 +22,7 @@ import com.intellij.openapi.application.invokeAndWaitIfNeed
import com.intellij.openapi.components.StateStorage
import com.intellij.openapi.components.stateStore
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.runModalTask
import com.intellij.openapi.project.Project
import com.intellij.util.SmartList
@@ -105,14 +106,7 @@ internal class SyncManager(private val icsManager: IcsManager, private val autoS
}
}
if (icsManager.readOnlySourcesManager.update(indicator)) {
invokeAndWaitIfNeed {
icsManager.schemeManagerFactory.value.process {
@Suppress("ConvertLambdaToReference")
it.reload()
}
}
}
updateCloudSchemes(indicator)
}
catch (e: ProcessCanceledException) {
LOG.debug("Canceled")
@@ -148,6 +142,25 @@ internal class SyncManager(private val icsManager: IcsManager, private val autoS
}
return updateResult
}
private fun updateCloudSchemes(indicator: ProgressIndicator) {
val changedRootDirs = icsManager.readOnlySourcesManager.update(indicator) ?: return
val schemeManagersToReload = SmartList<SchemeManagerImpl<*, *>>()
icsManager.schemeManagerFactory.value.process {
val fileSpec = toRepositoryPath(it.fileSpec, it.roamingType)
if (changedRootDirs.contains(fileSpec)) {
schemeManagersToReload.add(it)
}
}
if (schemeManagersToReload.isNotEmpty()) {
invokeAndWaitIfNeed {
for (schemeManager in schemeManagersToReload) {
schemeManager.reload()
}
}
}
}
}
internal fun updateStoragesFromStreamProvider(store: ComponentStoreImpl, updateResult: UpdateResult, messageBus: MessageBus, reloadAllSchemes: Boolean = false): Boolean {