More caches, better and generic cache code. Now Dracon listen to file changes to drop cached data. Implemented caches: - File contents in specific revision (never dropped) - Pijul ls and Pijul diff results - File Revision and File changes by patch - some others.. Dracon is incredible fast now, but still will take some time for bigger repos.

[?]
Apr 3, 2021, 3:18 AM
ISO7J5ZH5UB7NFZKTKKJQHQHCP4DWQ3F7SM2NDMVYJAGGIKDLX4QC

Dependencies

  • [2] Q35OTML2 Remove use of coroutines, which was blocking IntelliJ UI in larger repositories Improvements for bigger repositories, now Dracon caches the changes that happened in a revision in a file, so everytime Dracon needs to query the changes of a revision, it loads directly from memory instead of doing a full-scan in Pijul repository. For tiny projects it is not a problem, but for medium ones it takes more than five minutes to scan the entire repository (and it was tested with a repo of only 700 records, however there was changes that had more than 60.000 lines). The cache file is saved in IntelliJ Data Path (project specific) and is compressed with gzip, so it will not use so much disk space (the cost worths the gains).
  • [3] FNNW5IEA Added more plugin files to Pijul
  • [4] EAGIDXOL Build 2 to only listen to changes in project under pijul
  • [5] QXUEMZ3B Initial CahngeProvider
  • [6] GGYFPXND Initial plugin
  • [7] MTPTFTHG Initial plugin 2
  • [8] 7L5LODGZ Parse changes from `pijul change`
  • [9] 6CR2EFUN First ChangeProvider implementation!!! Wheehooo
  • [10] OPFG6CZ2 File status tracking supported.
  • [11] FRFFQV7V Basic show history support.
  • [12] ZCRW57C5 Improved support for revisions
  • [13] 5AUENX2Y Add support to view files affected by a revision
  • [14] NTRPUMVQ Improved README and added roadmap.
  • [15] B43WNBLF - Add Show History to Pijul menu - Always ignore .idea and .pijul in tracking. - Make findPijul a generic function to allow to find editor-server. - Only show one revision for directories. - Add `Hunk::resolvePath(Path)` to resolve the affected file to a Java NIO Path. - Fix StringOutOfBounds in Change Parsering Algorithm - Use editor-server instead of copie for interfacing with `pijul record` file. - Fix FileStatus provider not returning correctly for untracked files. - Add CommittedChangesProvider for Pijul.
  • [16] Q7FXTHVU First record support, YEAAAH, RECOOORD

Change contents

  • replacement in src/test/kotlin/com/github/jonathanxd/dracon/test/DraconTest.kt at line 443
    [3.28855][3.28855:28949]()
    context = Context(up = listOf(3.107), new = IntRange(0, 10), down = emptyList()),
    [3.28855]
    [3.28949]
    context = Context(up = listOf(3.107), new = Range(0, 10), down = emptyList()),
  • replacement in src/test/kotlin/com/github/jonathanxd/dracon/test/DraconTest.kt at line 504
    [3.32264][3.32264:32358]()
    context = Context(up = listOf(0.11), new = IntRange(12, 36), down = emptyList()),
    [3.32264]
    [3.32358]
    context = Context(up = listOf(0.11), new = Range(12, 36), down = emptyList()),
  • replacement in src/test/kotlin/com/github/jonathanxd/dracon/test/DraconTest.kt at line 514
    [3.32685][3.32685:32782]()
    context = Context(up = listOf(3.107), new = IntRange(843, 853), down = emptyList()),
    [3.32685]
    [3.32782]
    context = Context(up = listOf(3.107), new = Range(843, 853), down = emptyList()),
  • replacement in src/test/kotlin/com/github/jonathanxd/dracon/test/DraconTest.kt at line 556
    [3.35445][3.35445:35542]()
    context = Context(up = listOf(0.854), new = IntRange(855, 879), down = emptyList()),
    [3.35445]
    [3.35542]
    context = Context(up = listOf(0.854), new = Range(855, 879), down = emptyList()),
  • replacement in src/test/kotlin/com/github/jonathanxd/dracon/test/DraconTest.kt at line 576
    [3.36260][3.36260:36363]()
    context = Context(up = listOf(3.4473), new = IntRange(1584, 1698), down = listOf(3.4473)),
    [3.36260]
    [3.36363]
    context = Context(up = listOf(3.4473), new = Range(1584, 1698), down = listOf(3.4473)),
  • replacement in src/test/kotlin/com/github/jonathanxd/dracon/test/DraconTest.kt at line 599
    [3.37413][3.37413:37516]()
    context = Context(up = listOf(3.6839), new = IntRange(1699, 1950), down = listOf(3.6839)),
    [3.37413]
    [3.37516]
    context = Context(up = listOf(3.6839), new = Range(1699, 1950), down = listOf(3.6839)),
  • replacement in src/test/kotlin/com/github/jonathanxd/dracon/test/DraconTest.kt at line 707
    [3.44714][3.44714:44814]()
    context = Context(up = listOf(3.6847), new = IntRange(1951, 1964), down = emptyList()),
    [3.44714]
    [3.44814]
    context = Context(up = listOf(3.6847), new = Range(1951, 1964), down = emptyList()),
  • replacement in src/test/kotlin/com/github/jonathanxd/dracon/test/DraconTest.kt at line 723
    [3.45449][3.45449:45554]()
    context = Context(up = listOf(3.11015), new = IntRange(4000, 4103), down = listOf(3.11015)),
    [3.45449]
    [3.45554]
    context = Context(up = listOf(3.11015), new = Range(4000, 4103), down = listOf(3.11015)),
  • replacement in src/test/kotlin/com/github/jonathanxd/dracon/test/DraconTest.kt at line 739
    [3.46089][3.46089:46194]()
    context = Context(up = listOf(3.11075), new = IntRange(4104, 4156), down = listOf(3.11075)),
    [3.46089]
    [3.46194]
    context = Context(up = listOf(3.11075), new = Range(4104, 4156), down = listOf(3.11075)),
  • replacement in src/test/kotlin/com/github/jonathanxd/dracon/test/DraconTest.kt at line 755
    [3.46743][3.46743:46847]()
    context = Context(up = listOf(4.2779), new = IntRange(4157, 4222), down = listOf(3.11119)),
    [3.46743]
    [3.46847]
    context = Context(up = listOf(4.2779), new = Range(4157, 4222), down = listOf(3.11119)),
  • replacement in src/test/kotlin/com/github/jonathanxd/dracon/test/DraconTest.kt at line 781
    [3.47980][3.47980:48083]()
    context = Context(up = listOf(3.1361), new = IntRange(4223, 4490), down = listOf(3.1361)),
    [3.47980]
    [3.48083]
    context = Context(up = listOf(3.1361), new = Range(4223, 4490), down = listOf(3.1361)),
  • replacement in src/test/kotlin/com/github/jonathanxd/dracon/test/DraconTest.kt at line 868
    [3.53008][3.53008:53113]()
    context = Context(up = listOf(3.13611), new = IntRange(4491, 5952), down = listOf(3.13611)),
    [3.53008]
    [3.53113]
    context = Context(up = listOf(3.13611), new = Range(4491, 5952), down = listOf(3.13611)),
  • replacement in src/test/kotlin/com/github/jonathanxd/dracon/test/DraconTest.kt at line 884
    [3.53659][3.53659:53764]()
    context = Context(up = listOf(3.24239), new = IntRange(5953, 6018), down = listOf(3.24239)),
    [3.53659]
    [3.53764]
    context = Context(up = listOf(3.24239), new = Range(5953, 6018), down = listOf(3.24239)),
  • replacement in src/test/kotlin/com/github/jonathanxd/dracon/test/DraconTest.kt at line 900
    [3.54300][3.54300:54405]()
    context = Context(up = listOf(3.24475), new = IntRange(6019, 6074), down = listOf(3.24475)),
    [3.54300]
    [3.54405]
    context = Context(up = listOf(3.24475), new = Range(6019, 6074), down = listOf(3.24475)),
  • replacement in src/test/kotlin/com/github/jonathanxd/dracon/test/DraconTest.kt at line 918
    [3.55119][3.55119:55224]()
    context = Context(up = listOf(3.25153), new = IntRange(6075, 6178), down = listOf(3.25153)),
    [3.55119]
    [3.55224]
    context = Context(up = listOf(3.25153), new = Range(6075, 6178), down = listOf(3.25153)),
  • replacement in src/test/kotlin/com/github/jonathanxd/dracon/test/DraconTest.kt at line 928
    [3.55508][3.55508:55605]()
    context = Context(up = listOf(1.0), new = IntRange(6179, 6190), down = emptyList()),
    [3.55508]
    [3.55605]
    context = Context(up = listOf(1.0), new = Range(6179, 6190), down = emptyList()),
  • replacement in src/test/kotlin/com/github/jonathanxd/dracon/test/DraconTest.kt at line 939
    [3.55998][3.55998:56103]()
    context = Context(up = listOf(5.14803), new = IntRange(6193, 6231), down = listOf(5.14803)),
    [3.55998]
    [3.56103]
    context = Context(up = listOf(5.14803), new = Range(6193, 6231), down = listOf(5.14803)),
  • replacement in src/test/kotlin/com/github/jonathanxd/dracon/test/DraconTest.kt at line 961
    [3.56965][3.56965:57068]()
    context = Context(up = listOf(5.1482), new = IntRange(6232, 6394), down = listOf(5.1482)),
    [3.56965]
    [3.57068]
    context = Context(up = listOf(5.1482), new = Range(6232, 6394), down = listOf(5.1482)),
  • replacement in src/test/kotlin/com/github/jonathanxd/dracon/test/DraconTest.kt at line 1012
    [3.60956][3.60956:61057]()
    context = Context(up = listOf(2.59651), new = IntRange(6395, 8239), down = emptyList()),
    [3.60956]
    [3.61057]
    context = Context(up = listOf(2.59651), new = Range(6395, 8239), down = emptyList()),
  • edit in src/main/resources/META-INF/plugin.xml at line 5
    [3.1672][3.315:316]()
  • edit in src/main/resources/META-INF/plugin.xml at line 20
    [3.2210][3.538:539]()
  • edit in src/main/resources/META-INF/plugin.xml at line 34
    [3.2322]
    [3.2322]
  • edit in src/main/resources/META-INF/plugin.xml at line 72
    [3.2390]
    [3.2390]
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/vfs/PijulVirtualFileStatusProvider.kt at line 13
    [3.194]
    [3.0]
    import com.github.jonathanxd.dracon.cache.FileStatusCache
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/vfs/PijulVirtualFileStatusProvider.kt at line 17
    [3.108]
    [3.194]
    import com.intellij.openapi.components.service
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/vfs/PijulVirtualFileStatusProvider.kt at line 23
    [3.381]
    [3.381]
    import com.intellij.vcsUtil.VcsUtil
    import java.nio.file.Paths
    import java.time.Duration
    import java.time.Instant
    import java.util.concurrent.atomic.AtomicReference
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/vfs/PijulVirtualFileStatusProvider.kt at line 30
    [3.463]
    [3.49]
    private val cache = project.service<FileStatusCache>()
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/vfs/PijulVirtualFileStatusProvider.kt at line 34
    [3.121][3.1109:1182]()
    if (!Pijul.isUnderPijul(virtualFile) || isIdeaRoot(virtualFile))
    [3.121]
    [3.167]
    if (!Pijul.isUnderPijul(virtualFile) || isIdeaRoot(virtualFile) || !belongsToProject(virtualFile))
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/vfs/PijulVirtualFileStatusProvider.kt at line 40
    [3.118][3.109:188](),[3.534][3.109:188]()
    val status = pijul(this.project).fileStatus(this.project, virtualFile)
    [3.118]
    [3.188]
    val status = this.cache.load(Paths.get(VcsUtil.getFilePath(virtualFile).path))
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/vfs/PijulVirtualFileStatusProvider.kt at line 48
    [3.1226]
    [3.1226]
    fun belongsToProject(virtualFile: VirtualFile): Boolean =
    virtualFile.path.startsWith(project.basePath!!)
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/revision/RevisionContentResolver.kt at line 3
    [3.656]
    [3.656]
    import com.github.jonathanxd.dracon.pijul.SuccessStatusCode
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/revision/RevisionContentResolver.kt at line 60
    [3.1109]
    [3.1109]
    if (rollbackOp.statusCode !is SuccessStatusCode) {
    throw IllegalStateException("Failed to load state of file $filePath in revision $revisionHash. $rollbackOp")
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/revision/RevisionContentResolver.kt at line 66
    [3.1185]
    [3.1185]
    if (resetOp.statusCode !is SuccessStatusCode) {
    throw IllegalStateException("Failed to load state of file $filePath in revision $revisionHash during reset. $revisions")
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/revision/RevisionContentResolver.kt at line 71
    [3.1270]
    [3.1270]
    if (rollbackOp.statusCode !is SuccessStatusCode) {
    throw IllegalStateException("Failed to load state of file $filePath in revision $revisionHash during unrecord. $rollbackOp")
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/revision/PijulVcsFileRevision.kt at line 3
    [3.3155]
    [3.3155]
    import com.github.jonathanxd.dracon.cache.FileRevisionCache
    import com.intellij.openapi.components.service
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/revision/PijulVcsFileRevision.kt at line 38
    [3.2627]
    [3.3825]
    private val content = this.project.service<FileRevisionCache>().loadAsync(this)
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/revision/PijulVcsFileRevision.kt at line 41
    [3.3826][3.3826:3984]()
    override fun loadContent(): ByteArray =
    loadStateInRevision(this.revision.hash, this.project, vcsRoot, this.filePath).toByteArray(Charsets.UTF_8)
    [3.3826]
    [3.3984]
    override fun loadContent(): ByteArray = this.content.get()
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/revision/PijulRevisionNumber.kt at line 6
    [3.266]
    [3.266]
    import java.io.Serializable
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/revision/PijulRevisionNumber.kt at line 10
    [3.329][3.329:430]()
    class PijulRevisionNumber(val hash: String, val timestamp: ZonedDateTime) : ShortVcsRevisionNumber {
    [3.329]
    [3.430]
    class PijulRevisionNumber(val hash: String, val timestamp: ZonedDateTime) : ShortVcsRevisionNumber, Serializable {
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/revision/PijulRevisionNumber.kt at line 27
    [3.841]
    [3.841]
    companion object {
    private const val serialVersionUID: Long = 1
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/provider/PijulChangeProvider.kt at line 3
    [3.928]
    [3.119]
    import com.github.jonathanxd.dracon.cache.PijulLogEntryChangeCache
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/provider/PijulChangeProvider.kt at line 8
    [3.339]
    [3.928]
    import com.intellij.openapi.components.service
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/provider/PijulChangeProvider.kt at line 21
    [3.1193]
    [3.1193]
    private val logEntryChangeCache = project.service<PijulLogEntryChangeCache>()
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/provider/PijulChangeProvider.kt at line 52
    [3.4956][3.955:1178](),[3.955][3.955:1178]()
    val rootPath = Paths.get(root!!.path)
    val head = revisionMap.computeIfAbsent(rootPath) {
    pijul(this.project).latestRevisionNumber(this.project, root).result
    } ?: continue
    [3.4956]
    [3.1178]
    val rootPath = Paths.get(root.path)
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/provider/PijulChangeProvider.kt at line 54
    [3.1179][3.1179:1337]()
    val change = changesMap.computeIfAbsent(rootPath) {
    pijul(this.project).diff(this.project, root).result
    } ?: continue
    [3.1179]
    [3.1337]
    val head = this.logEntryChangeCache.loadRevision(rootAbsolute) {
    pijul(this.project).latestRevisionNumber(this.project, rootPath)
    }.result ?: continue
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/provider/PijulChangeProvider.kt at line 58
    [3.1338]
    [3.1338]
    val change = this.logEntryChangeCache.load(rootAbsolute) {
    pijul(this.project).diff(this.project, root)
    }.result ?: continue
  • file addition: PijulFilesStatus.kt (----------)
    [3.3420]
    package com.github.jonathanxd.dracon.pijul
    import com.intellij.openapi.vcs.FileStatus
    import java.nio.file.Path
    data class PijulFilesStatus(
    val changed: Map<Path, List<FileStatus>>,
    val tracked: List<Path>
    )
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/pijul/Pijul.kt at line 83
    [3.6838]
    [3.6838]
    @RequiresBackgroundThread
    fun fileStatus(project: Project, file: Path): PijulOperationResult<FileStatus>
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/pijul/Pijul.kt at line 88
    [3.1729]
    [3.1729]
    fun fileStatusMap(project: Project): PijulOperationResult<PijulFilesStatus>
    @RequiresBackgroundThread
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 14
    [3.2152][2.136:230]()
    data class Author(val name: String?, val fullName: String?, val email: String?): Serializable
    [3.2152]
    [3.61206]
    data class Author(val name: String?, val fullName: String?, val email: String?): Serializable {
    companion object {
    private const val serialVersionUID: Long = 1L
    }
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 29
    [3.61466][2.231:247]()
    ): Serializable
    [3.61466]
    [3.2153]
    ): Serializable {
    companion object {
    private const val serialVersionUID: Long = 1L
    }
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 43
    [3.61585][2.248:264]()
    ): Serializable
    [3.61585]
    [3.2155]
    ): Serializable {
    companion object {
    private const val serialVersionUID: Long = 1L
    }
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 56
    [2.357]
    [3.61754]
    private const val serialVersionUID: Long = 1L
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 64
    [3.61940][2.358:426]()
    data class IndexInt(val index: Int) : IntOrAsterisk(), Serializable
    [3.61940]
    [3.61994]
    data class IndexInt(val index: Int) : IntOrAsterisk(), Serializable {
    companion object {
    private const val serialVersionUID: Long = 1L
    }
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 89
    [3.62288][3.62288:62300]()
    UNKNOWN
    [3.62288]
    [3.62300]
    UNKNOWN;
    companion object {
    private const val serialVersionUID: Long = 1L
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 126
    [3.14114]
    [3.14114]
    companion object {
    private const val serialVersionUID: Long = 1L
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 144
    [3.14207]
    [3.14207]
    companion object {
    private const val serialVersionUID: Long = 1L
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 163
    [3.14300]
    [3.14300]
    companion object {
    private const val serialVersionUID: Long = 1L
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 180
    [3.14392]
    [3.14392]
    companion object {
    private const val serialVersionUID: Long = 1L
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 199
    [3.14485]
    [3.14485]
    companion object {
    private const val serialVersionUID: Long = 1L
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 218
    [3.14578]
    [3.14578]
    companion object {
    private const val serialVersionUID: Long = 1L
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 236
    [3.14671]
    [3.14671]
    companion object {
    private const val serialVersionUID: Long = 1L
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 255
    [3.14764]
    [3.14764]
    companion object {
    private const val serialVersionUID: Long = 1L
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 274
    [3.14857]
    [3.14857]
    companion object {
    private const val serialVersionUID: Long = 1L
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 285
    [3.65485][2.874:923]()
    data class Meta(val plain: String): Serializable
    [3.65485]
    [3.65520]
    data class Meta(val plain: String): Serializable {
    companion object {
    private const val serialVersionUID: Long = 1L
    }
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 296
    [3.65698][2.924:973]()
    data class Flag(val plain: String): Serializable
    [3.65698]
    [3.65733]
    data class Flag(val plain: String): Serializable {
    companion object {
    private const val serialVersionUID: Long = 1L
    }
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 306
    [3.65831][2.996:1012]()
    ): Serializable
    [3.65831]
    [2.1012]
    ): Serializable {
    companion object {
    private const val serialVersionUID: Long = 1L
    }
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 312
    [2.1013][2.1013:1074]()
    data class Range(val start: Int, val end: Int): Serializable
    [2.1013]
    [3.2465]
    data class Range(val start: Int, val end: Int): Serializable {
    companion object {
    private const val serialVersionUID: Long = 1L
    }
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 337
    [3.66380][3.66380:66401]()
    ZOMBIE_RESURRECT
    [3.66380]
    [3.66401]
    ZOMBIE_RESURRECT;
    companion object {
    private const val serialVersionUID: Long = 1L
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 344
    [3.66404][2.1180:1260]()
    data class LineChange(val type: LineChangeType, val data: String): Serializable
    [3.66404]
    [3.66470]
    data class LineChange(val type: LineChangeType, val data: String): Serializable {
    companion object {
    private const val serialVersionUID: Long = 1L
    }
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 358
    [3.66649]
    [3.66649]
    private const val serialVersionUID: Long = 1L
  • file addition: listeners (----------)
    [3.107]
  • file addition: PijulAsyncFileListener.kt (----------)
    [0.7108]
    package com.github.jonathanxd.dracon.listeners
    import com.github.jonathanxd.dracon.cache.FileStatusCache
    import com.github.jonathanxd.dracon.cache.PijulLogEntryChangeCache
    import com.intellij.openapi.components.service
    import com.intellij.openapi.externalSystem.autoimport.AsyncFileChangeListenerBase
    import com.intellij.openapi.project.Project
    import com.intellij.openapi.roots.ProjectRootManager
    import com.intellij.openapi.vfs.AsyncFileListener
    import com.intellij.openapi.vfs.VirtualFile
    import com.intellij.openapi.vfs.newvfs.events.VFileEvent
    import com.intellij.vcsUtil.VcsUtil
    import java.nio.file.Paths
    import java.util.concurrent.CopyOnWriteArrayList
    class PijulAsyncFileListener(val project: Project) : AsyncFileChangeListenerBase(), AsyncFileListener {
    private val fileStatusCache by lazy { this.project.service<FileStatusCache>() }
    private val pijulLogEntryChangeCache by lazy { this.project.service<PijulLogEntryChangeCache>() }
    override fun apply() {
    }
    override fun init() {
    }
    override fun isRelevant(file: VirtualFile, event: VFileEvent): Boolean {
    return ProjectRootManager.getInstance(this.project).fileIndex.isInContent(file)
    }
    override fun updateFile(file: VirtualFile, event: VFileEvent) {
    if (ProjectRootManager.getInstance(this.project).fileIndex.isInContent(file)) {
    this.fileStatusCache.unload(Paths.get(VcsUtil.getFilePath(file).path))
    this.pijulLogEntryChangeCache.unload(Paths.get(VcsUtil.getFilePath(file).path))
    }
    }
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/context/PijulVcsContext.kt at line 4
    [3.13132]
    [3.13132]
    import com.github.jonathanxd.dracon.listeners.PijulAsyncFileListener
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/context/PijulVcsContext.kt at line 6
    [3.13177]
    [3.13177]
    import com.intellij.openapi.Disposable
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/context/PijulVcsContext.kt at line 13
    [3.13464]
    [3.13464]
    import com.intellij.openapi.vfs.VirtualFileManager
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/context/PijulVcsContext.kt at line 20
    [3.13602][3.13602:13671]()
    class PijulVcsContext(val project: Project) {
    val root by lazy {
    [3.13602]
    [3.13671]
    class PijulVcsContext(val project: Project): Disposable {
    init {
    VirtualFileManager.getInstance().addAsyncFileListener(
    PijulAsyncFileListener(project),
    this
    )
    }
    override fun dispose() {
    }
    val root: Path get() {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/context/PijulVcsContext.kt at line 35
    [3.13735][3.13735:13879]()
    ProjectLevelVcsManager.getInstance(this.project).getRootsUnderVcs(pijulVcs(this.project))
    .first()
    .toNioPath()
    [3.13735]
    [3.13879]
    return ProjectLevelVcsManager.getInstance(this.project).getRootsUnderVcs(pijulVcs(this.project))
    .firstOrNull()
    ?.toNioPath() ?: Paths.get(project.basePath!!)
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 13
    [3.11015][2.1835:1885]()
    import com.github.jonathanxd.dracon.cache.HashKey
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 16
    [2.2054][2.2054:2135]()
    import com.github.jonathanxd.dracon.cache.persist.DraconPersistentStateComponent
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 44
    [3.11786][3.11786:11819](),[3.11819][3.15173:15256](),[3.15256][3.11819:11877](),[3.11819][3.11819:11877](),[3.11877][3.8268:8297]()
    import kotlinx.coroutines.flow.*
    import kotlinx.coroutines.future.asDeferred
    import kotlinx.coroutines.future.await
    import kotlinx.coroutines.runBlocking
    import java.io.File
    import java.net.ServerSocket
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 123
    [3.8497][3.15690:15858]()
    val fileStatusBasedInPijulLs = this.doExecutionWithMapper("file_status_from_ls", this.createExecPijulOperation(project, rootPath, listOf("ls"), delay = 10L)) {
    [3.8497]
    [3.8650]
    val fileStatusBasedInPijulLs =
    this.doExecutionWithMapper("file_status_from_ls", this.createExecPijulOperation(project, rootPath, listOf("ls"), log = false)) {
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 141
    [3.9137]
    [3.9137]
    }
    }
    @OptIn(ExperimentalPathApi::class)
    @RequiresBackgroundThread
    override fun fileStatus(project: Project, file: Path): PijulOperationResult<FileStatus> {
    val root = project.service<PijulVcsContext>().root
    val execution = this.createPainlessExecPijulOperation(project, root, listOf("diff", "--json"))
    val fileStatusBasedInPijulDiff = this.doExecutionWithMapper("file_status", execution) {
    try {
    val changes = PijulDiffJson.parseJson(it)
    val changeMap = changes.toFileStatusMap()
    val fPath = file.relativeTo(root).toString()
    if (fPath.isEmpty()) {
    FileStatus.SUPPRESSED
    } else {
    changeMap[fPath]?.firstOrNull()
    }
    } catch(t: Throwable) {
    logger<PijulCmd>().error(t)
    null
    }
    }
    val fileStatusBasedInPijulLs =
    this.doExecutionWithMapper("file_status_from_ls", this.createExecPijulOperation(project, root, listOf("ls"), log = false)) {
    val trackedFiles = it.split("\n")
    val fPath = file.relativeTo(root).toString()
    if (trackedFiles.contains(fPath)) {
    FileStatus.NOT_CHANGED
    } else {
    FileStatus.UNKNOWN
    }
    }
    return if (fileStatusBasedInPijulDiff.statusCode !is SuccessStatusCode
    || fileStatusBasedInPijulDiff.result == null
    || fileStatusBasedInPijulDiff.result == FileStatus.SUPPRESSED) {
    fileStatusBasedInPijulLs
    } else {
    fileStatusBasedInPijulDiff
    }
    }
    override fun fileStatusMap(project: Project): PijulOperationResult<PijulFilesStatus> {
    val root = project.service<PijulVcsContext>().root
    val fileStatusMap = mutableMapOf<Path, List<FileStatus>>()
    val tracked = mutableListOf<Path>()
    val execution = this.createPainlessExecPijulOperation(project, root, listOf("diff", "--json"))
    val fileStatusBasedInPijulDiff = this.doExecutionWithMapper("file_status", execution) {
    try {
    val changes = PijulDiffJson.parseJson(it)
    val changeMap = changes.toFileStatusMap()
    for (c in changeMap) {
    fileStatusMap[root.resolve(c.key)] = c.value
    }
    } catch(t: Throwable) {
    logger<PijulCmd>().error(t)
    null
    }
    }
    val fileStatusBasedInPijulLs =
    this.doExecutionWithMapper("file_status_from_ls", this.createExecPijulOperation(project, root, listOf("ls"), log = false)) {
    it.split("\n").mapTo(tracked) {
    root.resolve(it)
    }
    }
    if (fileStatusBasedInPijulDiff.statusCode !is SuccessStatusCode) {
    return fileStatusBasedInPijulDiff as PijulOperationResult<PijulFilesStatus>
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 219
    [3.9147]
    [3.9147]
    if (fileStatusBasedInPijulLs.statusCode !is SuccessStatusCode) {
    return fileStatusBasedInPijulLs as PijulOperationResult<PijulFilesStatus>
    }
    return PijulOperationResult("file_status", SuccessStatusCode, PijulFilesStatus(fileStatusMap, tracked))
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 246
    [3.10136][3.10136:10190](),[3.10190][3.15974:16059]()
    for (rollbackHash in rollbacks) {
    if (rollbackHash == hash)
    break;
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 247
    [3.16060][3.10190:10301](),[3.10190][3.10190:10301](),[3.10301][3.16061:16187](),[3.16187][3.10406:10608](),[3.10406][3.10406:10608]()
    val rollback = this.doExecution(
    "rollback_$rollbackHash",
    this.createPainlessExecPijulOperation(project, root, listOf("unrecord", "--reset", rollbackHash))
    )
    if (rollback.statusCode !is SuccessStatusCode) {
    return rollback as PijulOperationResult<Boolean>
    }
    [3.16060]
    [2.2260]
    val rollback = this.doExecution(
    "rollback_from_${hashList[0]}_until_$hash",
    this.createPainlessExecPijulOperation(project, root, listOf("unrecord", "--reset") + rollbacks)
    )
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 252
    [2.2261][2.2261:2311]()
    this.reset(project, root)
    [2.2261]
    [3.10608]
    if (rollback.statusCode !is SuccessStatusCode) {
    return rollback as PijulOperationResult<Boolean>
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 355
    [3.10848][3.16188:16292]()
    val resetExecution = this.createExecPijulOperation(project, root, listOf("reset"), delay = 10L)
    [3.10848]
    [3.10937]
    val resetExecution = this.createExecPijulOperation(project, root, listOf("reset"))
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 414
    [2.2313][2.2313:2389]()
    val change = this.pijulLogEntryCache.queryOrCompute(hash) {
    [2.2313]
    [2.2389]
    val change = this.pijulLogEntryCache.load(hash) {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 480
    [3.17714][2.2645:2721]()
    val change = this.pijulLogEntryCache.queryOrCompute(hash) {
    [3.17714]
    [2.2721]
    val change = this.pijulLogEntryCache.load(hash) {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 540
    [3.11387][3.18984:19121]()
    val change = this.doExecutionWithMapper("diff", this.createExecPijulOperation(project, rootPath, listOf("diff"), delay = 10L)) {
    [3.11387]
    [3.11509]
    val change = this.doExecutionWithMapper("diff", this.createExecPijulOperation(project, rootPath, listOf("diff"))) {
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 674
    [3.14283][3.20776:20919]()
    @Deprecated(message = "Deprecated in favor of createPainlessExecPijulOperation, which does not require a delay parameter to be provided!")
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 678
    [3.21092][3.21092:21172]()
    delay: Long = 1000L): PijulExecution {
    [3.21092]
    [3.14458]
    log: Boolean = true): PijulExecution {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 687
    [3.14691][2.3607:3714]()
    input.split("\n").forEach {
    draconConsoleWriter(project).logCommand("pijul", args, it)
    [3.14691]
    [2.3714]
    if (log) {
    input.split("\n").forEach {
    draconConsoleWriter(project).logCommand("pijul", args, it)
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 693
    [2.3725][2.3725:3837]()
    error.split("\n").forEach {
    draconConsoleWriter(project).logCommandError("pijul", args, it)
    [2.3725]
    [2.3837]
    if (log) {
    error.split("\n").forEach {
    draconConsoleWriter(project).logCommandError("pijul", args, it)
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 129
    [3.24702][3.24702:24777]()
    entry.hunks.filterIsInstance<HunkWithPath>().map { hunk ->
    [3.24702]
    [3.24777]
    entry.hunks.filterIsInstance<HunkWithPath>().groupBy { it.resolvePath(ctx.root) }.map { (p, hunks) ->
    val hunk = hunks.firstOrNull { it is EditHunk }
    ?: hunks.firstOrNull { it is ReplacementHunk }
    ?: hunks.firstOrNull { it is FileDelHunk }
    ?: hunks.firstOrNull { it is FileAddHunk }
    ?: hunks.first()
  • file move: cache (----------)cache (d--r------)
    [3.107]
    [2.8571]
  • file move: persist (----------)persist (d--r------)
    [2.8571]
    [2.8582]
  • file addition: PijulLogEntryChangeCache.kt (----------)
    [2.8571]
    package com.github.jonathanxd.dracon.cache
    import com.github.jonathanxd.dracon.context.PijulVcsContext
    import com.github.jonathanxd.dracon.log.PijulLogEntry
    import com.github.jonathanxd.dracon.pijul.PijulOperationResult
    import com.github.jonathanxd.dracon.pijul.SuccessStatusCode
    import com.github.jonathanxd.dracon.revision.PijulRevisionNumber
    import com.intellij.openapi.components.Service
    import com.intellij.openapi.components.service
    import com.intellij.openapi.project.Project
    import java.nio.file.Path
    import kotlin.io.path.ExperimentalPathApi
    import kotlin.io.path.relativeTo
    @Suppress("UnstableApiUsage")
    @OptIn(ExperimentalPathApi::class)
    @Service
    class PijulLogEntryChangeCache(val project: Project) {
    private val dataCache = DataCache<String, PijulLogEntry>(project, "path_change")
    private val revisionDataCache = DataCache<String, PijulRevisionNumber>(project, "revision")
    fun load(path: Path, compute: () -> PijulOperationResult<PijulLogEntry>): PijulOperationResult<PijulLogEntry> {
    val ctx = this.project.service<PijulVcsContext>()
    val relativePath = path.relativeTo(ctx.root).toString()
    return this.dataCache.queryOrLoad(relativePath,
    { compute() },
    { it.statusCode is SuccessStatusCode && it.result != null },
    {it.result!!},
    { PijulOperationResult("file_changes", SuccessStatusCode, it) }
    )
    }
    fun loadRevision(path: Path, compute: () -> PijulOperationResult<PijulRevisionNumber>): PijulOperationResult<PijulRevisionNumber> {
    val ctx = this.project.service<PijulVcsContext>()
    val relativePath = path.relativeTo(ctx.root).toString()
    return this.revisionDataCache.queryOrLoad(relativePath,
    { compute() },
    { it.statusCode is SuccessStatusCode },
    {it.result!!},
    { PijulOperationResult("revision", SuccessStatusCode, it) }
    )
    }
    fun unload(path: Path) {
    val ctx = this.project.service<PijulVcsContext>()
    val relativePath = path.relativeTo(ctx.root).toString()
    this.dataCache.unload(relativePath)
    this.dataCache.unload("")
    this.revisionDataCache.unload(relativePath)
    this.revisionDataCache.unload("")
    }
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cache/PijulLogEntryCache.kt at line 3
    [2.11442][2.11442:11587]()
    import com.github.jonathanxd.dracon.cache.persist.createLogEntriesPersist
    import com.github.jonathanxd.dracon.cache.persist.toPijulLogEntriesMap
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cache/PijulLogEntryCache.kt at line 7
    [2.11808][2.11808:11936]()
    import com.intellij.openapi.project.getProjectDataPath
    import java.nio.file.Files
    import java.util.concurrent.ConcurrentHashMap
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cache/PijulLogEntryCache.kt at line 10
    [2.12016][2.12016:12218]()
    private val map = ConcurrentHashMap<String, PijulLogEntry>()
    private val cachePath = project.getProjectDataPath("com.jonathanxd.dracon")
    private val cacheFile = cachePath.resolve("log.obj")
    [2.12016]
    [2.12218]
    private val dataCache = DataCache<String, PijulLogEntry>(project, "change")
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cache/PijulLogEntryCache.kt at line 12
    [2.12219][2.12219:13103]()
    init {
    Files.createDirectories(cachePath)
    if (Files.exists(this.cacheFile)) {
    try {
    this.map.putAll(this.cacheFile.toPijulLogEntriesMap())
    } catch (e: Throwable) {
    Files.delete(this.cacheFile)
    }
    }
    }
    fun queryOrCompute(hash: String, compute: () -> PijulOperationResult<PijulLogEntry>): PijulOperationResult<PijulLogEntry> {
    return if (!this.map.containsKey(hash)) {
    val computeEntry = compute()
    if (computeEntry.statusCode !is SuccessStatusCode) {
    return computeEntry
    }
    this.map[hash] = computeEntry.result!!
    this.cacheFile.createLogEntriesPersist(this.map)
    computeEntry
    } else {
    PijulOperationResult("change-$hash", SuccessStatusCode, this.map[hash])
    }
    [2.12219]
    [2.13103]
    fun load(hash: String, compute: () -> PijulOperationResult<PijulLogEntry>): PijulOperationResult<PijulLogEntry> {
    return this.dataCache.queryOrLoad(hash,
    { compute() },
    { it.statusCode is SuccessStatusCode },
    {it.result!!},
    { PijulOperationResult("change-$hash", SuccessStatusCode, it) }
    )
  • file addition: FileStatusCache.kt (----------)
    [2.8571]
    package com.github.jonathanxd.dracon.cache
    import com.github.jonathanxd.dracon.context.PijulVcsContext
    import com.github.jonathanxd.dracon.pijul.PijulOperationResult
    import com.github.jonathanxd.dracon.pijul.SuccessStatusCode
    import com.github.jonathanxd.dracon.pijul.pijul
    import com.intellij.openapi.components.Service
    import com.intellij.openapi.components.service
    import com.intellij.openapi.project.Project
    import com.intellij.openapi.vcs.FileStatus
    import com.intellij.openapi.vcs.FileStatusFactory
    import java.io.Serializable
    import java.nio.file.Path
    import kotlin.io.path.ExperimentalPathApi
    import kotlin.io.path.relativeTo
    @OptIn(ExperimentalPathApi::class)
    @Service
    class FileStatusCache(val project: Project) {
    private val cache = DataCache<String, CacheablePijulFileStatus>(this.project, "file_status")
    init {
    // Pre-load status
    this.cache.lock()
    try {
    val ctx = this.project.service<PijulVcsContext>()
    val map = pijul(project).fileStatusMap(project)
    if (map.result != null) {
    for (change in map.result.changed) {
    if (change.value.isNotEmpty()) {
    val path = change.key.relativeTo(ctx.root)
    this.cache.queryOrLoad(path.toString()) {
    change.value.first().toPijul()
    }
    }
    }
    for (tracked in map.result.tracked) {
    val path = tracked.relativeTo(ctx.root)
    this.cache.queryOrLoad(path.toString()) {
    FileStatus.NOT_CHANGED.toPijul()
    }
    }
    }
    } finally {
    this.cache.unlock()
    }
    }
    fun load(path: Path): PijulOperationResult<FileStatus> {
    val ctx = this.project.service<PijulVcsContext>()
    return this.cache.queryOrLoad(path.relativeTo(ctx.root).toString(),
    { pijul(project).fileStatus(project, path) },
    { it.statusCode is SuccessStatusCode },
    { it.result!!.toPijul() },
    { PijulOperationResult("file_status", SuccessStatusCode, it.toFileStatus()) }
    )
    }
    fun unload(path: Path) {
    val ctx = this.project.service<PijulVcsContext>()
    val relativePath = path.relativeTo(ctx.root).toString()
    this.cache.unload(relativePath)
    }
    }
    data class CacheablePijulFileStatus(val id: String) : Serializable {
    companion object {
    private const val serialVersionUID: Long = 1
    }
    }
    fun FileStatus.toPijul(): CacheablePijulFileStatus = CacheablePijulFileStatus(this.id)
    fun CacheablePijulFileStatus.toFileStatus(): FileStatus =
    try {
    FileStatus::class.java.getDeclaredField(this.id).get(null) as FileStatus
    } catch (t: Throwable) {
    FileStatusFactory.getInstance().allFileStatuses.first {
    it.id == this.id
    }
    }
  • file addition: FileRevisionCache.kt (----------)
    [2.8571]
    package com.github.jonathanxd.dracon.cache
    import com.github.jonathanxd.dracon.context.PijulVcsContext
    import com.github.jonathanxd.dracon.revision.PijulVcsFileRevision
    import com.github.jonathanxd.dracon.revision.loadStateInRevision
    import com.intellij.openapi.components.Service
    import com.intellij.openapi.components.service
    import com.intellij.openapi.project.Project
    import java.io.Serializable
    import java.util.concurrent.CompletableFuture
    import java.util.concurrent.Executors
    import java.util.concurrent.locks.ReentrantLock
    @Service
    class FileRevisionCache(val project: Project) {
    private val cache = DataCache<FileRevisionRef, ByteArray>(this.project, "file_revision")
    fun loadAsync(rev: PijulVcsFileRevision): CompletableFuture<ByteArray> {
    val root = project.service<PijulVcsContext>().root
    val fileRev = FileRevisionRef(rev.filePath.toAbsolutePath().toString(), rev.revision.hash)
    return this.cache.queryOrLoadAsync(fileRev) {
    loadStateInRevision(
    rev.revision.hash,
    this.project,
    root,
    rev.filePath
    ).toByteArray(Charsets.UTF_8)
    }
    }
    }
    data class FileRevisionRef(
    val filePath: String,
    val revision: String
    ): Serializable
  • file addition: DataCache.kt (----------)
    [2.8571]
    package com.github.jonathanxd.dracon.cache
    import com.intellij.openapi.project.Project
    import com.intellij.openapi.project.getProjectDataPath
    import java.io.ObjectInputStream
    import java.io.ObjectOutputStream
    import java.nio.file.Files
    import java.nio.file.Path
    import java.nio.file.StandardOpenOption
    import java.util.concurrent.CompletableFuture
    import java.util.concurrent.ConcurrentHashMap
    import java.util.concurrent.Executors
    import java.util.concurrent.locks.ReentrantLock
    import java.util.zip.GZIPInputStream
    import java.util.zip.GZIPOutputStream
    @Suppress("UnstableApiUsage")
    class DataCache<K, V>(val project: Project,
    val name: String) {
    private val cachePath = project.getProjectDataPath("com.github.jonathanxd.dracon")
    private val cacheFile = cachePath.resolve("$name.gz")
    private val manager = DataCacheManager<K, V>(this.cacheFile)
    private val lock = ReentrantLock()
    private val updateExecutor = Executors.newCachedThreadPool()
    private val inMemory = ConcurrentHashMap<K, V>()
    init {
    this.manager.load()?.let {
    this.inMemory.putAll(it)
    }
    }
    fun lock() {
    this.lock.lock()
    }
    fun unlock() {
    this.lock.unlock()
    }
    fun unload(key: K) {
    this.lock.lock()
    try {
    this.inMemory.remove(key)
    this.manager.write(this.inMemory)
    } finally {
    this.lock.unlock()
    }
    }
    fun queryOrLoad(key: K, compute: (K) -> V): V {
    this.lock.lock()
    try {
    return if (!this.inMemory.containsKey(key)) {
    val computeEntry = compute(key)
    this.inMemory[key] = computeEntry
    this.manager.write(this.inMemory)
    computeEntry
    } else {
    this.inMemory[key]!!
    }
    } finally {
    this.lock.unlock();
    }
    }
    fun <I> queryOrLoad(key: K,
    compute: (K) -> I,
    filter: (I) -> Boolean,
    iMapper: (I) -> V,
    vMapper: (V) -> I): I {
    this.lock.lock()
    try {
    return if (!this.inMemory.containsKey(key)) {
    val computeEntry = compute(key)
    if (!filter(computeEntry)) {
    return computeEntry
    }
    this.inMemory[key] = iMapper(computeEntry!!)
    this.manager.write(this.inMemory)
    computeEntry
    } else {
    vMapper(this.inMemory[key]!!)
    }
    } finally {
    this.lock.unlock();
    }
    }
    fun queryOrLoadAsync(key: K, compute: (K) -> V): CompletableFuture<V> {
    if (this.inMemory.containsKey(key)) {
    return CompletableFuture.completedFuture(this.inMemory[key]!!)
    } else {
    return CompletableFuture.supplyAsync({
    this.lock.lock()
    try {
    val computeEntry = compute(key)
    this.inMemory[key] = computeEntry
    this.manager.write(this.inMemory)
    computeEntry
    } finally {
    this.lock.unlock()
    }
    }, this.updateExecutor)
    }
    }
    fun <I> queryOrLoadAsync(key: K,
    compute: (K) -> I,
    filter: (I) -> Boolean,
    iMapper: (I) -> V,
    vMapper: (V) -> I): CompletableFuture<I> {
    if (this.inMemory.containsKey(key)) {
    return CompletableFuture.completedFuture(vMapper(this.inMemory[key]!!))
    } else {
    return CompletableFuture.supplyAsync({
    this.lock.lock()
    try {
    val computeEntry = compute(key)
    if (!filter(computeEntry)) {
    computeEntry
    } else {
    this.inMemory[key] = iMapper(computeEntry!!)
    this.manager.write(this.inMemory)
    computeEntry
    }
    } finally {
    this.lock.unlock()
    }
    }, this.updateExecutor)
    }
    }
    }
    class DataCacheManager<K, V>(val path: Path) {
    init {
    Files.createDirectories(this.path.parent)
    }
    fun load(): Map<K, V>? {
    if (!Files.exists(this.path)) return null
    try {
    Files.newInputStream(this.path).use { stream ->
    GZIPInputStream(stream).use { gz ->
    ObjectInputStream(gz).use { reader ->
    return reader.readObject() as Map<K, V>
    }
    }
    }
    } catch (t: Throwable) {
    t.printStackTrace()
    Files.delete(this.path)
    return null
    }
    }
    fun write(data: Map<K, V>) {
    Files.newOutputStream(this.path, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING).use { writer ->
    GZIPOutputStream(writer).use { compress ->
    ObjectOutputStream(compress).use { oos ->
    oos.writeObject(data)
    }
    }
    }
    }
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/PijulVcs.kt at line 16
    [3.24239]
    [3.5953]
    import com.github.jonathanxd.dracon.listeners.PijulAsyncFileListener
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/PijulVcs.kt at line 20
    [3.23533]
    [3.23533]
    import com.intellij.openapi.Disposable
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/PijulVcs.kt at line 32
    [3.23640][3.16304:16362]()
    import com.intellij.openapi.vcs.history.VcsRevisionNumber
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/PijulVcs.kt at line 34
    [3.24519]
    [3.24519]
    import com.intellij.openapi.vfs.VirtualFileManager
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/PijulVcs.kt at line 48
    [3.24882]
    [3.24882]
    override fun activate() {
    super.activate()
    }