- 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.

[?]
Apr 1, 2021, 5:04 PM
B43WNBLFFR2UQIH3C6KIZAQTAEQOQM3J3IYLGQMVGJHYOME73OKQC

Dependencies

  • [2] 5AUENX2Y Add support to view files affected by a revision
  • [3] ZCRW57C5 Improved support for revisions
  • [4] 6CR2EFUN First ChangeProvider implementation!!! Wheehooo
  • [5] QXUEMZ3B Initial CahngeProvider
  • [6] FRFFQV7V Basic show history support.
  • [7] FNNW5IEA Added more plugin files to Pijul
  • [8] 7L5LODGZ Parse changes from `pijul change`
  • [9] Q7FXTHVU First record support, YEAAAH, RECOOORD
  • [10] OPFG6CZ2 File status tracking supported.
  • [11] EAGIDXOL Build 2 to only listen to changes in project under pijul
  • [*] GGYFPXND Initial plugin
  • [*] MTPTFTHG Initial plugin 2

Change contents

  • edit in src/main/resources/META-INF/plugin.xml at line 62
    [3.1052]
    [14.2072]
    <reference ref="Vcs.ShowHistoryForBlock"/>
    <reference ref="Vcs.ShowTabbedFileHistory"/>
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/vfs/PijulVirtualFileStatusProvider.kt at line 27
    [3.192][3.0:79](),[3.534][3.0:79]()
    if (virtualFile.name == ".idea" || virtualFile.name == "dracon_diffs")
    [3.192]
    [3.79]
    if (virtualFile.name == ".idea" || virtualFile.name == ".pijul")
  • file addition: Application.kt (----------)
    [3.1784]
    package com.github.jonathanxd.dracon.util
    import java.io.File
    import java.nio.file.Files
    import java.nio.file.Path
    import java.nio.file.Paths
    fun findBinary(app: String): String {
    // Works in Windows, Linux and MacOS when app is installed with cargo.
    val localPijul = findCargo(app)
    // For Homebrew/Linuxbrew installations
    val brewPijul = findBrew(app)
    // For *nix only.
    val usrBinPijul = Paths.get(File.pathSeparator, "usr", "bin", app).asExecutableStringOrNull()
    val usrLocalBinPijul = Paths.get(File.pathSeparator, "usr", "local", "bin", app).asExecutableStringOrNull()
    val binPijul = Paths.get(File.pathSeparator, "bin", app).asExecutableStringOrNull()
    // For Windows only.
    // Windows could download Pijul binaries from https://github.com/boringcactus/pijul-windows-builds/releases/latest
    // However, Dracon plugin could not detect Pijul outside from these directories, for the cases where
    // Pijul is not in these locations, a search through $PATH variable will be made, so if the $PATH is correctly
    // configured to point to Pijul executable, then it will be found, this applies to all OSes.
    val programFiles = Paths.get("C:"+ File.pathSeparator, "Program Files", app, "$app.exe").asExecutableStringOrNull()
    val programFiles86 = Paths.get("C:"+ File.pathSeparator, "Program Files (x86)", app, "$app.exe").asExecutableStringOrNull()
    return localPijul
    ?: brewPijul
    ?: usrBinPijul
    ?: usrLocalBinPijul
    ?: binPijul
    ?: programFiles
    ?: programFiles86
    ?: findExecutableOnPath(app)
    ?: app
    }
    private fun Path.asExecutableStringOrNull(): String? =
    this.existsOrNull()?.isRegularFileOrNull()?.isExecutableOrNull()?.toAbsolutePath()?.toString()
    private fun findCargo(app: String): String? {
    return System.getProperty("user.dir")?.let {
    Paths.get(it, ".cargo", "bin", app)
    }?.asExecutableStringOrNull()
    }
    private fun findBrew(app: String): String? {
    return System.getenv("HOMEBREW_PREFIX")?.ifBlank { null }?.ifEmpty { null }?.let {
    Paths.get(it, "bin", app)
    }?.asExecutableStringOrNull()
    }
    fun findExecutableOnPath(name: String): String? {
    for (dirname in System.getenv("PATH").split(File.pathSeparator)) {
    val path = Paths.get(dirname, name)
    if (Files.isRegularFile(path) && Files.isExecutable(path)) {
    return path.toAbsolutePath().toString()
    }
    }
    return null
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/provider/PijulHistoryProvider.kt at line 102
    [3.7230]
    [3.7230]
    val ctx = this.project.service<PijulVcsContext>()
    val pathToView = ctx.resolveUnderVcs(path)
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/provider/PijulHistoryProvider.kt at line 116
    [3.7565][2.1292:1416]()
    // TODO: Should we limit to show only one revision when introspecting directories instead of all revisions?
    [3.7565]
    [3.3657]
    val deleted = it.hunks.filterIsInstance<HunkWithPath>().filter {
    it.resolvePath(ctx.root) == path
    }.filterIsInstance<FileDelHunk>().isNotEmpty()
    partner.acceptRevision(
    PijulVcsFileRevision(
    this.project,
    root.toNioPath(),
    pathToView,
    PijulRevisionNumber(it.changeHash, it.date),
    it.authors.map { VcsUserImpl(it.name ?: "", it.email ?: "") }.filter { it.name.isNotEmpty() },
    it.message,
    currentChannel,
    deleted
    )
    )
    /*// TODO: Should we limit to show only one revision when introspecting directories instead of all revisions?
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/provider/PijulHistoryProvider.kt at line 150
    [3.7989][3.4443:4461]()
    }
    [3.7989]
    [3.4461]
    }*/
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/provider/PijulChangeProvider.kt at line 59
    [3.1449][3.4957:5031]()
    val path = Paths.get(dir.path, hunk.resolvedPath)
    [3.1449]
    [3.1515]
    val path = hunk.resolvePath(rootPath)
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/provider/PijulChangeProvider.kt at line 69
    [3.2148][3.5112:5186]()
    val path = Paths.get(dir.path, hunk.resolvedPath)
    [3.2148]
    [3.2214]
    val path = hunk.resolvePath(rootPath)
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/provider/PijulChangeProvider.kt at line 84
    [3.2853][3.5272:5346]()
    val path = Paths.get(dir.path, hunk.resolvedPath)
    [3.2853]
    [3.2919]
    val path = hunk.resolvePath(rootPath)
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/provider/PijulChangeProvider.kt at line 99
    [3.3552][3.5347:5421]()
    val path = Paths.get(dir.path, hunk.resolvedPath)
    [3.3552]
    [3.3618]
    val path = hunk.resolvePath(rootPath)
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/pijul/Pijul.kt at line 14
    [3.13038]
    [3.1584]
    import com.github.jonathanxd.dracon.editor.EditorServer
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/pijul/Pijul.kt at line 104
    [3.5757]
    [3.4856]
    @RequiresBackgroundThread
    fun record(project: Project, root: Path, editorServerConsumer: (EditorServer) -> Unit): PijulOperationResult<String>
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 372
    [3.70435]
    [3.70435]
    if (lastFound == this.length)
    break;
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 672
    [3.81773][3.81773:81817]()
    val end = this.indexOf('\n', start + 1)
    [3.81773]
    [3.81817]
    val end = this.indexOf('\n', start + 1).let {
    if (it == -1) this.length
    else it
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 744
    [3.83920]
    [3.83920]
    if (lastLine == this.length) {
    break;
    }
  • file addition: editor (----------)
    [3.107]
  • file addition: EditorServer.kt (----------)
    [0.4403]
    package com.github.jonathanxd.dracon.editor
    import com.github.jonathanxd.dracon.util.findBinary
    import java.net.ServerSocket
    import java.net.URI
    import java.net.http.HttpClient
    import java.net.http.HttpRequest
    import java.net.http.HttpResponse
    import java.time.Duration
    import java.time.Instant
    class EditorServer(val port: Int, val isClosed: () -> Boolean) {
    private var connected: Boolean = false
    private val client = HttpClient.newHttpClient()
    private lateinit var content: String
    fun connectAndRetrieveContent() {
    val start = Instant.now()
    while (!this.isClosed()) {
    if (Duration.between(start, Instant.now()).seconds > 10) {
    throw IllegalStateException("Could not connect to editor server! Timeout after 10 seconds.")
    }
    try {
    val response = this.client.send(
    HttpRequest.newBuilder(URI.create("http://0.0.0.0:$port/read"))
    .GET()
    .version(HttpClient.Version.HTTP_2)
    .build(),
    HttpResponse.BodyHandlers.ofString()
    )
    if (response.statusCode() == 200) {
    this.connected = true
    this.content = response.body();
    break;
    }
    } catch (t: Throwable) {
    }
    Thread.sleep(200)
    }
    }
    fun content() = this.content
    fun connected() = this.connected
    fun write(text: String) {
    if (this.isClosed()) {
    throw IllegalStateException("Could not write: editor-server is already closed.")
    }
    if (!this.connected) {
    throw IllegalStateException("Could not write: Not connected to editor-server!")
    }
    val response = this.client.send(
    HttpRequest.newBuilder(URI.create("http://0.0.0.0:$port/write"))
    .POST(HttpRequest.BodyPublishers.ofString(text))
    .version(HttpClient.Version.HTTP_2)
    .build(),
    HttpResponse.BodyHandlers.ofString()
    )
    handleResponse(response)
    }
    private fun handleResponse(response: HttpResponse<*>) {
    if (response.statusCode() != 200) {
    throw IllegalStateException("editor-server responded with $response.")
    }
    }
    fun close() {
    if (this.isClosed()) {
    throw IllegalStateException("Could not close: editor-server is already closed.")
    }
    if (!this.connected) {
    throw IllegalStateException("Could not close: Not connected to editor-server!")
    }
    try {
    // This will make the connection close immediately
    // thus throwing an exception.
    this.client.send(
    HttpRequest.newBuilder(URI.create("http://0.0.0.0:$port/close"))
    .GET()
    .version(HttpClient.Version.HTTP_2)
    .build(),
    HttpResponse.BodyHandlers.ofString()
    )
    } catch (t: Throwable) {
    }
    }
    }
    fun freePort(): Int = ServerSocket(0).use {
    it.localPort
    }
    fun editorServerPath(): String = findBinary("editor-server")
  • file move: dialog (----------)dialog (d--r------)
    [3.107]
    [2.2837]
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/dialog/PijulExpertRecordDialog.kt at line 4
    [2.5990]
    [2.5990]
    import com.github.jonathanxd.dracon.editor.EditorServer
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/dialog/PijulExpertRecordDialog.kt at line 48
    [2.7858]
    [2.7858]
    val editorServer: EditorServer,
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/dialog/PijulExpertRecordDialog.kt at line 96
    [2.9568][2.9568:9672]()
    val record = pijul(this.project).recordFromString(this.project, this.vcsRoot, this.editor.text)
    [2.9568]
    [2.9672]
    this.editorServer.write(this.editor.text)
    this.editorServer.close()
    /*val record = pijul(this.project).recordFromString(this.project, this.vcsRoot, this.editor.text)
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/dialog/PijulExpertRecordDialog.kt at line 123
    [2.10672][2.10672:10682]()
    }
    [2.10672]
    [2.10682]
    }*/
  • file move: context (----------)context (d--r------)
    [3.107]
    [2.13018]
  • file move: completion (----------)completion (d--r------)
    [3.107]
    [2.14863]
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 16
    [3.6340]
    [3.15130]
    import com.github.jonathanxd.dracon.editor.EditorServer
    import com.github.jonathanxd.dracon.editor.editorServerPath
    import com.github.jonathanxd.dracon.editor.freePort
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 25
    [3.2779][3.11119:11347](),[3.4222][3.11119:11347](),[2.17007][3.11119:11347](),[3.11119][3.11119:11347]()
    import com.github.jonathanxd.dracon.util.existsOrNull
    import com.github.jonathanxd.dracon.util.isExecutableOrNull
    import com.github.jonathanxd.dracon.util.isRegularFileOrNull
    import com.github.jonathanxd.dracon.util.linesToFlow
    [2.17007]
    [3.6341]
    import com.github.jonathanxd.dracon.util.*
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 46
    [3.11877]
    [3.11877]
    import java.net.ServerSocket
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 129
    [3.3672][3.8785:8806]()
    null
    [3.3672]
    [3.8806]
    FileStatus.UNKNOWN
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 229
    [3.7168]
    [3.7168]
    }
    }
    override fun record(
    project: Project,
    root: Path,
    editorServerConsumer: (EditorServer) -> Unit
    ): PijulOperationResult<String> {
    val arguments = mutableListOf("record")
    val operation = this.createPainlessExecPijulWithEditorServer(
    this.project,
    root,
    arguments,
    editorServerConsumer
    )
    return this.doExecutionWithMapper("record", operation) {
    it
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 741
    [3.23205][3.15488:15654](),[3.15488][3.15488:15654]()
    private fun findPijul(): String {
    // Works in Windows, Linux and MacOS when Pijul is installed with cargo.
    val localPijul = this.findCargoPijul()
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 742
    [3.15655][3.15655:15748]()
    // For Homebrew/Linuxbrew installations
    val brewPijul = this.findBrewPijul()
    [3.15655]
    [3.15748]
    /**
    * Creates a [PijulExecution] operation that could be executed at any time. This operation uses Kotlin Coroutines
    * and can be executed immediately through [doExecution] or through [doExecutionWithMapper].
    *
    * This implementation does not requires a delay value to be provided, like [createExecPijulOperation] does, instead
    * it uses the kotlin conversion from `CompletionStage` to `Coroutines` and awaits the process through [Process.onExit].
    *
    * [doExecution] and [doExecutionWithMapper] does execution by scheduling task to [Dispatchers.IO], instead of Main Thread,
    * offloading the Process execution handling to a different scheduler. However, mapping operation of [doExecutionWithMapper]
    * is not offloaded from the caller context.
    *
    */
    @RequiresBackgroundThread
    private fun createPainlessExecPijulWithEditorServer(project: Project,
    dir: Path,
    args: List<String>,
    editorServerConsumer: (EditorServer) -> Unit): PijulExecution {
    val freePort = freePort()
    val process = ProcessBuilder()
    .apply {
    environment()["EDITOR_SERVER_PORT"] = freePort.toString()
    environment()["VISUAL"] = editorServerPath()
    environment()["EDITOR"] = editorServerPath()
    }
    .command(listOf(this.findPijul()) + args)
    .directory(dir.toFile())
    .start()
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 770
    [3.15749][3.15749:16112]()
    // For *nix only.
    val usrBinPijul = Paths.get(File.pathSeparator, "usr", "bin", "pijul").asPijulExecutableStringOrNull()
    val usrLocalBinPijul = Paths.get(File.pathSeparator, "usr", "local", "bin", "pijul").asPijulExecutableStringOrNull()
    val binPijul = Paths.get(File.pathSeparator, "bin", "pijul").asPijulExecutableStringOrNull()
    [3.15749]
    [3.16112]
    editorServerConsumer(EditorServer(freePort) {
    !process.isAlive
    })
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 774
    [3.16113][3.16113:16870]()
    // For Windows only.
    // Windows could download Pijul binaries from https://github.com/boringcactus/pijul-windows-builds/releases/latest
    // However, Dracon plugin could not detect Pijul outside from these directories, for the cases where
    // Pijul is not in these locations, a search through $PATH variable will be made, so if the $PATH is correctly
    // configured to point to Pijul executable, then it will be found, this applies to all OSes.
    val programFiles = Paths.get("C:"+ File.pathSeparator, "Program Files", "pijul", "pijul.exe").asPijulExecutableStringOrNull()
    val programFiles86 = Paths.get("C:"+ File.pathSeparator, "Program Files (x86)", "pijul", "pijul.exe").asPijulExecutableStringOrNull()
    [3.16113]
    [3.16870]
    val input = process.inputStream
    val error = process.errorStream
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 777
    [3.16871]
    [3.16871]
    return PijulExecution(
    input.linesToFlow().onEach {
    draconConsoleWriter(project).logCommand("pijul", args, it)
    },
    error.linesToFlow().onEach {
    draconConsoleWriter(project).logCommandError("pijul", args, it)
    },
    flow {
    process.onExit().await()
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 787
    [3.16872][3.16872:17143]()
    return localPijul
    ?: brewPijul
    ?: usrBinPijul
    ?: usrLocalBinPijul
    ?: binPijul
    ?: programFiles
    ?: programFiles86
    ?: this.findExecutableOnPath("pijul")
    ?: "pijul"
    }
    [3.16872]
    [3.17143]
    val exit = process.exitValue()
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 789
    [3.17144][3.17144:17311]()
    private fun Path.asPijulExecutableStringOrNull(): String? =
    this.existsOrNull()?.isRegularFileOrNull()?.isExecutableOrNull()?.toAbsolutePath()?.toString()
    [3.17144]
    [3.17311]
    if (exit == 0) {
    draconConsoleWriter(project).logCommand("pijul", args, "<Exit status> $exit")
    } else {
    draconConsoleWriter(project).logCommandError("pijul", args, "<Exit status> $exit")
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 795
    [3.17312][3.17312:17504]()
    private fun findCargoPijul(): String? {
    return System.getProperty("user.dir")?.let {
    Paths.get(it, ".cargo", "bin", "pijul")
    }?.asPijulExecutableStringOrNull()
    [3.17312]
    [3.17504]
    emit(exit)
    }.flowOn(Dispatchers.IO)
    )
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 800
    [3.17511][3.17511:17736]()
    private fun findBrewPijul(): String? {
    return System.getenv("HOMEBREW_PREFIX")?.ifBlank { null }?.ifEmpty { null }?.let {
    Paths.get(it, "bin", "pijul")
    }?.asPijulExecutableStringOrNull()
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 801
    [3.17737][3.17737:18067]()
    fun findExecutableOnPath(name: String): String? {
    for (dirname in System.getenv("PATH").split(File.pathSeparator)) {
    val path = Paths.get(dirname, name)
    if (Files.isRegularFile(path) && Files.isExecutable(path)) {
    return path.toAbsolutePath().toString()
    }
    }
    [3.17737]
    [3.18067]
    private fun findPijul(): String = findBinary("pijul")
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 803
    [3.18068][3.18068:18094](),[3.18094][3.12900:12901]()
    return null
    }
  • file move: changes (----------)changes (d--r------)
    [3.107]
    [2.19780]
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 14
    [2.20409][2.20409:20454]()
    import com.intellij.openapi.util.io.FileUtil
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 16
    [2.20535][2.20535:20694]()
    import com.intellij.openapi.vcs.changes.ChangeList
    import com.intellij.openapi.vcs.changes.ChangesUtil
    import com.intellij.openapi.vcs.history.VcsFileRevision
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 23
    [2.21126]
    [2.21126]
    import com.intellij.util.text.trimMiddle
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 25
    [2.21181][2.21181:21274]()
    import com.intellij.vcs.log.VcsFullCommitDetails
    import com.intellij.vcs.log.util.VcsLogUtil
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 26
    [2.21310][2.21310:21351]()
    import org.jetbrains.annotations.NotNull
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 50
    [2.22358][2.22358:22414]()
    this.getChanges(settings, location, maxCount) {
    [2.22358]
    [2.22414]
    this.getChanges(settings, maxCount) {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 63
    [2.22702][2.22702:22757]()
    getChanges(settings, location, maxCount) {
    [2.22702]
    [2.22757]
    getChanges(settings, maxCount) {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 71
    [2.22877][2.22877:23111]()
    private fun getChanges(settings: ChangeBrowserSettings,
    location: RepositoryLocation,
    maxCount: Int,
    consumer: (PijulCommittedChangeList) -> Unit) {
    [2.22877]
    [2.23111]
    private fun getChanges(
    settings: ChangeBrowserSettings,
    maxCount: Int,
    revision: VcsRevisionNumber? = null,
    consumer: (PijulCommittedChangeList) -> Unit
    ) {
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 121
    [2.24470]
    [2.24470]
    }?.filter {
    revision == null || it.revision.hash == revision.asString()
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 125
    [2.24534]
    [2.24534]
    entry.message.trimMiddle(20),
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 127
    [2.24565][2.24565:24585]()
    "",
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 169
    [2.26231][2.26231:26268]()
    return if (i == 0) {
    [2.26231]
    [2.26268]
    return if (i + 1 >= allRevisions.size) {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 172
    [2.26318][2.26318:26358]()
    allRevisions[i - 1]
    [2.26318]
    [2.26358]
    allRevisions[i + 1]
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 196
    [2.27013][2.27013:27106]()
    val allRevisions = pijul(this.project).allRevisions(this.project, ctx.root).result!!
    [2.27013]
    [2.27106]
    val changes = mutableListOf<CommittedChangeList>()
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 198
    [2.27107][2.27107:28028]()
    val rev = pijul(this.project).log(this.project, ctx.root).result?.entries?.filter {
    it.revision.hash == number.asString()
    }?.map { entry ->
    PijulCommittedChangeList(
    entry.message,
    "",
    entry.authors.firstOrNull()?.name ?: "No author",
    Date.from(entry.date.toInstant()),
    entry.hunks.filterIsInstance<HunkWithPath>().map { hunk ->
    val beforeRevision =
    if (hunk is FileAddHunk) null
    else findARevisionBefore(entry.changeHash, allRevisions)?.let {
    PijulContentRevision(
    ctx.root,
    hunk.resolvePath(ctx.root),
    it,
    this.project
    )
    }
    [2.27107]
    [2.28028]
    this.getChanges(ChangeBrowserSettings(), 1, number) {
    changes.add(it)
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 202
    [2.28029][2.28029:28728]()
    val afterRevision =
    if (hunk is FileDelHunk) null
    else PijulContentRevision(
    ctx.root,
    hunk.resolvePath(ctx.root),
    entry.revision,
    this.project
    )
    Change(
    beforeRevision,
    afterRevision,
    hunk.status
    )
    }.toMutableList(),
    entry.revision,
    false,
    pijulVcs(this.project)
    )
    }?.firstOrNull() ?: return null
    [2.28029]
    [2.28728]
    val rev = changes.firstOrNull() ?: return null
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/actions/PijulExpertRecord.kt at line 5
    [2.30335]
    [2.30335]
    import com.github.jonathanxd.dracon.i18n.DraconBundle
    import com.github.jonathanxd.dracon.pijul.NonZeroExitStatusCode
    import com.github.jonathanxd.dracon.pijul.SuccessStatusCode
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/actions/PijulExpertRecord.kt at line 9
    [2.30383]
    [2.30383]
    import com.intellij.notification.Notification
    import com.intellij.notification.NotificationGroup
    import com.intellij.notification.NotificationType
    import com.intellij.notification.Notifications
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/actions/PijulExpertRecord.kt at line 24
    [2.30882]
    [2.30882]
    private val EXPERT_MODE_GROUP =
    NotificationGroup.createIdWithTitle("Expert Mode", DraconBundle.message("expert.mode.notification.group.id"))
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/actions/PijulExpertRecord.kt at line 32
    [2.31177]
    [2.31177]
    val record = pijul(project).record(project, root) {
    it.connectAndRetrieveContent()
    if (it.connected()) {
    PijulExpertRecordDialog(project, root, it, it.content()).showAndGet()
    }
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/actions/PijulExpertRecord.kt at line 41
    [2.31178][2.31178:31221]()
    if (recordString.result != null) {
    [2.31178]
    [2.31221]
    if (record.statusCode is SuccessStatusCode) {
    val result = record.result!!
    val hash = result.substring(result.indexOf("Hash:") + "Hash:".length).trim()
    Notifications.Bus.notify(
    Notification(
    EXPERT_MODE_GROUP,
    DraconBundle.message("expert.mode.notification.title"),
    DraconBundle.message("expert.mode.notification.success", hash),
    NotificationType.ERROR,
    ),
    project
    )
    } else {
    record.statusCode as NonZeroExitStatusCode
    Notifications.Bus.notify(
    Notification(
    EXPERT_MODE_GROUP,
    DraconBundle.message("expert.mode.notification.title"),
    DraconBundle.message("expert.mode.notification.failure", record.statusCode.exitCode, record.statusCode.message),
    NotificationType.INFORMATION,
    ),
    project
    )
    }
    /*if (recordString.result != null) {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/actions/PijulExpertRecord.kt at line 69
    [2.31386][2.31386:31401]()
    /*
    [2.31386]
    [2.31401]
    *//*
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/actions/PijulExpertRecord.kt at line 79
    [2.31963][2.31963:31979]()
    */
    [2.31963]
    [2.31979]
    *//*
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/actions/PijulExpertRecord.kt at line 84
    [2.32067][2.32067:32136]()
    /*FileEditorManager.getInstance(project).openTextEditor(
    [2.32067]
    [2.32136]
    *//*FileEditorManager.getInstance(project).openTextEditor(
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/actions/PijulExpertRecord.kt at line 87
    [2.32257][2.32257:32283]()
    )*/
    }
    [2.32257]
    [2.32283]
    )*//*
    }*/
  • edit in README.md at line 33
    [3.1213336]
    [3.1213336]
    Recently versions of Dracon requires [editor-server](https://crates.io/crates/editor-server) to be installed in order to work, the final
    release version will come bundled with the [editor-server](https://crates.io/crates/editor-server).