Ready for pijul push! First nightly build will be released shortly!

[?]
Apr 4, 2021, 9:48 PM
OMZXJL6QA6INENIEAARSWYFHOPMLTP4WRCVI646GQVJVWCH3LENQC

Dependencies

  • [2] A7IL6I3V More files to support .ignore
  • [3] ISO7J5ZH 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.
  • [4] QXUEMZ3B Initial CahngeProvider
  • [5] FNNW5IEA Added more plugin files to Pijul
  • [6] 5AUENX2Y Add support to view files affected by a revision
  • [7] 37OJKSWJ Improved caching code a lot
  • [8] 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).
  • [9] Q7FXTHVU First record support, YEAAAH, RECOOORD
  • [10] 2N67RQZC Add auto installation support and cache content of ContentRevision
  • [11] 6CR2EFUN First ChangeProvider implementation!!! Wheehooo
  • [12] 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.
  • [13] ZCRW57C5 Improved support for revisions
  • [14] OPFG6CZ2 File status tracking supported.
  • [15] FRFFQV7V Basic show history support.
  • [*] 7L5LODGZ Parse changes from `pijul change`
  • [*] GGYFPXND Initial plugin
  • [*] MTPTFTHG Initial plugin 2

Change contents

  • file addition: DraconPushChangesTest.kt (----------)
    [17.11189]
    package com.github.jonathanxd.dracon.test
    import com.github.jonathanxd.dracon.push.parsePijulPushChanges
    import io.kotest.core.spec.style.ShouldSpec
    import io.kotest.matchers.shouldBe
    class DraconPushChangesTest : ShouldSpec({
    should("correctly parse a 'pijul push' text with example credit") {
    val text = """
    # Please select the changes to push. The lines that contain just a
    # valid hash, and no other character (except possibly a newline), will
    # be pushed.
    ZCRW57C5MSBXYGUMGQTZNHGHO4HGHFBICW53X5I2IMGP3H2CKWRQC
    Dependencies: Q7FXTHVUPVAFMNY277C3NFJO3VXLZU5G6C6UYSD5QPURHSG3A7OQC EAGIDXOLFTHZMZ77ZWAM7MVVUBBXJMZD7RZUNBHJPYRFGGKILGVAC
    Author: [{ name = "Jonathan", full_name = "Jonathan H. R. Lopes", email = "jhrldev@gmail.com" }]
    Date: 2021-03-31 22:43:40.062881279 UTC
    Improved support for revisions
    5AUENX2YJVFNKZUSPEPDNLLL7TKZS2WTFC6CABWSZK2EC4MNCRQAC
    Dependencies: ZCRW57C5MSBXYGUMGQTZNHGHO4HGHFBICW53X5I2IMGP3H2CKWRQC
    Author: [{ name = "Jonathan", full_name = "Jonathan H. R. Lopes", email = "jhrldev@gmail.com" }]
    Date: 2021-04-01 00:07:39.373781350 UTC
    Add support to view files affected by a revision
    B43WNBLFFR2UQIH3C6KIZAQTAEQOQM3J3IYLGQMVGJHYOME73OKQC
    Dependencies: 5AUENX2YJVFNKZUSPEPDNLLL7TKZS2WTFC6CABWSZK2EC4MNCRQAC
    Author: [{ name = "Jonathan", full_name = "Jonathan H. R. Lopes", email = "jhrldev@gmail.com" }]
    Date: 2021-04-01 17:04:54.758320581 UTC
    - 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.
    Q35OTML226J2HZLHOCPV5OY6ZUM2XU4RZBE5E3GDWVHVFASHFEJAC
    Dependencies: B43WNBLFFR2UQIH3C6KIZAQTAEQOQM3J3IYLGQMVGJHYOME73OKQC
    Author: [{ name = "Jonathan", full_name = "Jonathan H. R. Lopes", email = "jhrldev@gmail.com" }]
    Date: 2021-04-02 21:31:47.581509792 UTC
    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).
    ISO7J5ZH5UB7NFZKTKKJQHQHCP4DWQ3F7SM2NDMVYJAGGIKDLX4QC
    Dependencies: Q35OTML226J2HZLHOCPV5OY6ZUM2XU4RZBE5E3GDWVHVFASHFEJAC
    Author: [{ name = "Jonathan", full_name = "Jonathan H. R. Lopes", email = "jhrldev@gmail.com" }]
    Date: 2021-04-03 03:18:36.900275901 UTC
    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.
    2N67RQZCVGL6GYJJLM2US4YVCEIUK25AHCLD66C7HR4PPTNUOCWAC
    Dependencies: ISO7J5ZH5UB7NFZKTKKJQHQHCP4DWQ3F7SM2NDMVYJAGGIKDLX4QC
    Author: [{ name = "Jonathan", full_name = "Jonathan H. R. Lopes", email = "jhrldev@gmail.com" }]
    Date: 2021-04-04 03:15:58.713132084 UTC
    Add auto installation support and cache content of ContentRevision
    37OJKSWJFDRHNWQW6P7HSZX6OWZWVNCJ2IFT42O5TANQF7VOVX6AC
    Dependencies: A7JOR7M3BUKXYMMAR43IK4GXFXGI33HM6H6LZHDES3HWW6GYFAYAC G54TB4QZZ6OYC2KZTB7KUVW3NJ6VASH7WPNFU2IATPZWM3POIRNQC 2N67RQZCVGL6GYJJLM2US4YVCEIUK25AHCLD66C7HR4PPTNUOCWAC
    Author: [{ name = "Jonathan", full_name = "Jonathan H. R. Lopes", email = "jhrldev@gmail.com" }]
    Date: 2021-04-04 12:07:50.967878750 UTC
    Improved caching code a lot
    A7IL6I3VCB3F3QMYQFPXBL33DN5XDGGQPZIBZRHYSQBSIUBBFQJQC
    Dependencies: 37OJKSWJFDRHNWQW6P7HSZX6OWZWVNCJ2IFT42O5TANQF7VOVX6AC
    Author: [{ name = "Jonathan", full_name = "Jonathan H. R. Lopes", email = "jhrldev@gmail.com" }]
    Date: 2021-04-04 18:38:01.065118605 UTC
    More files to support .ignore
    """.trimIndent()
    val push = text.parsePijulPushChanges()
    push.toString() shouldBe "PijulPushChanges(entries=[PijulPushEntry(hash=ZCRW57C5MSBXYGUMGQTZNHGHO4HGHFBICW53X5I2IMGP3H2CKWRQC, dependencies=[Q7FXTHVUPVAFMNY277C3NFJO3VXLZU5G6C6UYSD5QPURHSG3A7OQC, EAGIDXOLFTHZMZ77ZWAM7MVVUBBXJMZD7RZUNBHJPYRFGGKILGVAC], authors=[Author(name=Jonathan, fullName=Jonathan H. R. Lopes, email=jhrldev@gmail.com)], date=2021-03-31T22:43:40.062881279Z[Etc/UTC], message= Improved support for revisions\n" +
    "), PijulPushEntry(hash=5AUENX2YJVFNKZUSPEPDNLLL7TKZS2WTFC6CABWSZK2EC4MNCRQAC, dependencies=[ZCRW57C5MSBXYGUMGQTZNHGHO4HGHFBICW53X5I2IMGP3H2CKWRQC], authors=[Author(name=Jonathan, fullName=Jonathan H. R. Lopes, email=jhrldev@gmail.com)], date=2021-04-01T00:07:39.373781350Z[Etc/UTC], message= Add support to view files affected by a revision\n" +
    "), PijulPushEntry(hash=B43WNBLFFR2UQIH3C6KIZAQTAEQOQM3J3IYLGQMVGJHYOME73OKQC, dependencies=[5AUENX2YJVFNKZUSPEPDNLLL7TKZS2WTFC6CABWSZK2EC4MNCRQAC], authors=[Author(name=Jonathan, fullName=Jonathan H. R. Lopes, email=jhrldev@gmail.com)], date=2021-04-01T17:04:54.758320581Z[Etc/UTC], message= - Add Show History to Pijul menu\n" +
    " - Always ignore .idea and .pijul in tracking.\n" +
    " - Make findPijul a generic function to allow to find editor-server.\n" +
    " - Only show one revision for directories.\n" +
    " - Add `Hunk::resolvePath(Path)` to resolve the affected file to a Java NIO Path.\n" +
    " - Fix StringOutOfBounds in Change Parsering Algorithm\n" +
    " - Use editor-server instead of copie for interfacing with `pijul record` file.\n" +
    " - Fix FileStatus provider not returning correctly for untracked files.\n" +
    " - Add CommittedChangesProvider for Pijul.\n" +
    "), PijulPushEntry(hash=Q35OTML226J2HZLHOCPV5OY6ZUM2XU4RZBE5E3GDWVHVFASHFEJAC, dependencies=[B43WNBLFFR2UQIH3C6KIZAQTAEQOQM3J3IYLGQMVGJHYOME73OKQC], authors=[Author(name=Jonathan, fullName=Jonathan H. R. Lopes, email=jhrldev@gmail.com)], date=2021-04-02T21:31:47.581509792Z[Etc/UTC], message= Remove use of coroutines, which was blocking IntelliJ UI in larger repositories\n" +
    "\n" +
    " 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).\n" +
    "\n" +
    " 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).\n" +
    "\n" +
    "), PijulPushEntry(hash=ISO7J5ZH5UB7NFZKTKKJQHQHCP4DWQ3F7SM2NDMVYJAGGIKDLX4QC, dependencies=[Q35OTML226J2HZLHOCPV5OY6ZUM2XU4RZBE5E3GDWVHVFASHFEJAC], authors=[Author(name=Jonathan, fullName=Jonathan H. R. Lopes, email=jhrldev@gmail.com)], date=2021-04-03T03:18:36.900275901Z[Etc/UTC], message= More caches, better and generic cache code.\n" +
    "\n" +
    "\n" +
    " Now Dracon listen to file changes to drop cached data.\n" +
    "\n" +
    " Implemented caches:\n" +
    "\n" +
    " - File contents in specific revision (never dropped)\n" +
    " - Pijul ls and Pijul diff results\n" +
    " - File Revision and File changes by patch\n" +
    " - some others..\n" +
    "\n" +
    "\n" +
    " Dracon is incredible fast now, but still will take some time for bigger repos.\n" +
    "), PijulPushEntry(hash=2N67RQZCVGL6GYJJLM2US4YVCEIUK25AHCLD66C7HR4PPTNUOCWAC, dependencies=[ISO7J5ZH5UB7NFZKTKKJQHQHCP4DWQ3F7SM2NDMVYJAGGIKDLX4QC], authors=[Author(name=Jonathan, fullName=Jonathan H. R. Lopes, email=jhrldev@gmail.com)], date=2021-04-04T03:15:58.713132084Z[Etc/UTC], message= Add auto installation support and cache content of ContentRevision\n" +
    "), PijulPushEntry(hash=37OJKSWJFDRHNWQW6P7HSZX6OWZWVNCJ2IFT42O5TANQF7VOVX6AC, dependencies=[A7JOR7M3BUKXYMMAR43IK4GXFXGI33HM6H6LZHDES3HWW6GYFAYAC, G54TB4QZZ6OYC2KZTB7KUVW3NJ6VASH7WPNFU2IATPZWM3POIRNQC, 2N67RQZCVGL6GYJJLM2US4YVCEIUK25AHCLD66C7HR4PPTNUOCWAC], authors=[Author(name=Jonathan, fullName=Jonathan H. R. Lopes, email=jhrldev@gmail.com)], date=2021-04-04T12:07:50.967878750Z[Etc/UTC], message= Improved caching code a lot\n" +
    "), PijulPushEntry(hash=A7IL6I3VCB3F3QMYQFPXBL33DN5XDGGQPZIBZRHYSQBSIUBBFQJQC, dependencies=[37OJKSWJFDRHNWQW6P7HSZX6OWZWVNCJ2IFT42O5TANQF7VOVX6AC], authors=[Author(name=Jonathan, fullName=Jonathan H. R. Lopes, email=jhrldev@gmail.com)], date=2021-04-04T18:38:01.065118605Z[Etc/UTC], message= More files to support .ignore\n" +
    "\n" +
    ")])"
    }
    })
  • edit in src/main/resources/messages/DraconBundle.properties at line 19
    [3.55]
    [3.0]
    action.Pijul.Push.text=Push Changes...
  • edit in src/main/resources/messages/DraconBundle.properties at line 23
    [19.135]
    [18.166]
    action.Pijul.push.enter.remote=Enter Remote
  • edit in src/main/resources/messages/DraconBundle.properties at line 38
    [3.125]
    [3.125]
    push.button.text=Push
  • edit in src/main/resources/messages/DraconBundle.properties at line 41
    [3.126]
    [3.126]
    push.notification.group.id=Push changes
    push.notification.title=Push
    push.notification.success=Successfully pushed changes.
    push.notification.failure=Failed to push changes with exit code <bold>{0}</bold> and message: <tt>{1}</tt>.
  • edit in src/main/resources/messages/DraconBundle.properties at line 89
    [3.9409]
    remote.invalid.remote.text=Invalid remote server {0}...
  • edit in src/main/resources/META-INF/plugin.xml at line 35
    [2.466]
    [3.9510]
    <pushSupport implementation="com.github.jonathanxd.dracon.push.PijulPushSupport"/>
  • edit in src/main/resources/META-INF/plugin.xml at line 68
    [3.787]
    [19.1246]
    <action id="Pijul.Push" class="com.github.jonathanxd.dracon.actions.PijulPushRecord"/>
  • edit in src/main/resources/META-INF/plugin.xml at line 90
    [19.2097]
    [19.2097]
    <reference ref="Pijul.Push"/>
  • file move: repository (----------)repository (d--r------)
    [3.107]
    [2.1127]
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/repository/PijulRepository.kt at line 4
    [2.3849]
    [2.3849]
    import com.github.jonathanxd.dracon.config.PijulConfig
    import com.github.jonathanxd.dracon.context.PijulVcsContext
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/repository/PijulRepository.kt at line 28
    [2.4892]
    [2.4892]
    val pijulConfig: PijulConfig by lazy {
    PijulConfig(project.service<PijulVcsContext>().root)
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/repository/PijulRepository.kt at line 62
    [2.5741][2.5741:5854]()
    pijul(this.project).channel(project, project.baseDir).result?.channels?.firstOrNull { it.current }?.name
    [2.5741]
    [2.5854]
    pijul(this.project).channel(project, project.baseDir).result?.channels?.firstOrNull { it.current }?.name?.trim()
  • file addition: push (----------)
    [3.107]
  • file addition: PijulVcsFullCommitDetails.kt (----------)
    [0.10965]
    package com.github.jonathanxd.dracon.push
    import com.github.jonathanxd.dracon.log.PijulHash
    import com.intellij.openapi.project.Project
    import com.intellij.openapi.vcs.changes.Change
    import com.intellij.openapi.vfs.VfsUtil
    import com.intellij.openapi.vfs.VirtualFile
    import com.intellij.openapi.vfs.VirtualFileManager
    import com.intellij.vcs.log.Hash
    import com.intellij.vcs.log.VcsFullCommitDetails
    import com.intellij.vcs.log.VcsUser
    import com.intellij.vcs.log.impl.VcsUserImpl
    import java.nio.file.Path
    class PijulVcsFullCommitDetails(
    val root: Path,
    val project: Project,
    val entry: PijulPushEntry,
    val changeRetriever: (String) -> List<Change>
    ) : VcsFullCommitDetails {
    override fun getId(): Hash =
    PijulHash(this.entry.hash)
    override fun getParents(): MutableList<Hash> =
    this.entry.dependencies.map(::PijulHash).toMutableList()
    override fun getTimestamp(): Long = this.entry.date.toEpochSecond()
    override fun getRoot(): VirtualFile =
    VirtualFileManager.getInstance().findFileByNioPath(this.root)!!
    override fun getSubject(): String =
    if (this.entry.message.isNotEmpty()) ""
    else this.entry.message.split("\n")[0]
    override fun getAuthor(): VcsUser =
    this.entry.authors.firstOrNull()?.let {
    VcsUserImpl(it.name ?: "", it.email ?: "")
    } ?: VcsUserImpl("", "")
    override fun getCommitter(): VcsUser =
    this.author
    override fun getAuthorTime(): Long =
    this.timestamp
    override fun getCommitTime(): Long =
    this.timestamp
    override fun getFullMessage(): String =
    this.entry.message
    override fun getChanges(): MutableCollection<Change> =
    this.changeRetriever(this.entry.hash).toMutableList()
    override fun getChanges(parent: Int): MutableCollection<Change> =
    this.changeRetriever(this.parents[parent].asString()).toMutableList()
    }
  • file addition: PijulTarget.kt (----------)
    [0.10965]
    package com.github.jonathanxd.dracon.push
    import com.intellij.dvcs.push.PushTarget
    import com.intellij.openapi.util.NlsSafe
    data class PijulTarget(@NlsSafe val target: String, @NlsSafe val channel: String) : PushTarget {
    override fun hasSomethingToPush(): Boolean = true
    override fun getPresentation(): String = this.target
    override fun toString(): String = this.getPresentation()
    }
  • file addition: PijulPusher.kt (----------)
    [0.10965]
    package com.github.jonathanxd.dracon.push
    import com.github.jonathanxd.dracon.context.PijulVcsContext
    import com.github.jonathanxd.dracon.dialog.PijulChangesDialog
    import com.github.jonathanxd.dracon.i18n.DraconBundle
    import com.github.jonathanxd.dracon.pijul.NonZeroExitStatusCode
    import com.github.jonathanxd.dracon.pijul.SuccessStatusCode
    import com.github.jonathanxd.dracon.pijul.pijul
    import com.github.jonathanxd.dracon.repository.PijulRepository
    import com.intellij.dvcs.push.PushSpec
    import com.intellij.dvcs.push.Pusher
    import com.intellij.dvcs.push.VcsPushOptionValue
    import com.intellij.notification.Notification
    import com.intellij.notification.NotificationGroup
    import com.intellij.notification.NotificationType
    import com.intellij.notification.Notifications
    import com.intellij.openapi.components.service
    import com.intellij.openapi.project.Project
    class PijulPusher : Pusher<PijulRepository, PijulPushSource, PijulTarget>() {
    private val PUSH_GROUP =
    NotificationGroup.createIdWithTitle("Push Changes", DraconBundle.message("push.notification.group.id"))
    override fun push(
    pushSpecs: Map<PijulRepository, PushSpec<PijulPushSource, PijulTarget>>,
    vcsPushOptionValue: VcsPushOptionValue?, force: Boolean
    ) {
    for ((repository, pijulSpec) in pushSpecs) {
    val destination: PijulTarget = pijulSpec.target
    val source: PijulPushSource = pijulSpec.source
    val project: Project = repository.project
    val ctx = project.service<PijulVcsContext>()
    val push = pijul(project).push(
    project,
    ctx.root,
    source.channel,
    destination.channel,
    destination.target
    ) {
    it.connectAndRetrieveContent()
    if (it.connected()) {
    PijulChangesDialog(project, ctx.root, it, it.content(),
    DraconBundle.message("action.Pijul.Push.text"),
    DraconBundle.message("push.button.text")).showAndGet()
    }
    }
    if (push.statusCode is SuccessStatusCode) {
    Notifications.Bus.notify(
    Notification(
    PUSH_GROUP,
    DraconBundle.message("push.notification.title"),
    DraconBundle.message("push.notification.success"),
    NotificationType.ERROR,
    ),
    project
    )
    } else {
    push.statusCode as NonZeroExitStatusCode
    Notifications.Bus.notify(
    Notification(
    PUSH_GROUP,
    DraconBundle.message("push.notification.title"),
    DraconBundle.message("push.notification.failure", push.statusCode.exitCode, push.statusCode.message),
    NotificationType.INFORMATION,
    ),
    project
    )
    }
    }
    }
    }
  • file addition: PijulPushTargetPanel.kt (----------)
    [0.10965]
    package com.github.jonathanxd.dracon.push
    import com.github.jonathanxd.dracon.i18n.DraconBundle
    import com.github.jonathanxd.dracon.repository.PijulRepository
    import com.intellij.dvcs.DvcsUtil
    import com.intellij.dvcs.push.PushTargetPanel
    import com.intellij.dvcs.push.VcsError
    import com.intellij.dvcs.push.ui.PushTargetEditorListener
    import com.intellij.dvcs.push.ui.PushTargetTextField
    import com.intellij.dvcs.push.ui.VcsEditableTextComponent
    import com.intellij.openapi.editor.event.DocumentEvent
    import com.intellij.openapi.editor.event.DocumentListener
    import com.intellij.openapi.ui.ValidationInfo
    import com.intellij.openapi.util.NlsSafe
    import com.intellij.openapi.util.text.HtmlChunk
    import com.intellij.openapi.util.text.StringUtil
    import com.intellij.ui.ColoredTreeCellRenderer
    import com.intellij.util.textCompletion.TextFieldWithCompletion
    import com.intellij.ui.SimpleTextAttributes
    import java.awt.BorderLayout
    class PijulPushTargetPanel(repository: PijulRepository, source: PijulPushSource, defaultTarget: PijulTarget?) :
    PushTargetPanel<PijulTarget>() {
    private val myRepository: PijulRepository
    private val myBranchName: @NlsSafe String?
    private val myDestTargetPanel: TextFieldWithCompletion
    private val myTargetRenderedComponent: VcsEditableTextComponent
    override fun render(
    renderer: ColoredTreeCellRenderer,
    isSelected: Boolean,
    isActive: Boolean,
    forceRenderedText: String?
    ) {
    if (forceRenderedText != null) {
    myDestTargetPanel.text = forceRenderedText
    renderer.append(forceRenderedText)
    return
    }
    val targetText = myDestTargetPanel.text
    if (StringUtil.isEmptyOrSpaces(targetText)) {
    renderer.append(
    DraconBundle.message("action.Pijul.push.enter.remote"),
    SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES,
    myTargetRenderedComponent
    )
    }
    myTargetRenderedComponent.setSelected(isSelected)
    myTargetRenderedComponent.setTransparent(!isActive)
    myTargetRenderedComponent.render(renderer)
    }
    override fun getValue(): PijulTarget {
    return createValidPushTarget()
    }
    private fun createValidPushTarget(): PijulTarget {
    return PijulTarget(myDestTargetPanel.text, myBranchName!!)
    }
    override fun fireOnCancel() {
    myDestTargetPanel.text = myTargetRenderedComponent.text
    }
    override fun fireOnChange() {
    myTargetRenderedComponent.updateLinkText(myDestTargetPanel.text)
    }
    override fun verify(): ValidationInfo? {
    return if (StringUtil.isEmptyOrSpaces(myDestTargetPanel.text)) {
    ValidationInfo(VcsError.createEmptyTargetError(DvcsUtil.getShortRepositoryName(myRepository)).text, this)
    } else null
    }
    override fun setFireOnChangeAction(action: Runnable) {
    // no extra changing components => ignore
    }
    override fun addTargetEditorListener(listener: PushTargetEditorListener) {
    myDestTargetPanel.addDocumentListener(object : DocumentListener {
    override fun documentChanged(e: DocumentEvent) {
    listener.onTargetInEditModeChanged(myDestTargetPanel.text)
    }
    })
    }
    init {
    layout = BorderLayout()
    isOpaque = false
    myRepository = repository
    myBranchName = source.channel
    val targetVariants: List<String> = repository.pijulConfig.remotes.keys.toList()
    val defaultText = defaultTarget?.presentation ?: ""
    myTargetRenderedComponent = VcsEditableTextComponent(HtmlChunk.link("", defaultText).toString(), null)
    myDestTargetPanel = PushTargetTextField(repository.project, targetVariants, defaultText)
    add(myDestTargetPanel, BorderLayout.CENTER)
    }
    }
  • file addition: PijulPushSupport.kt (----------)
    [0.10965]
    package com.github.jonathanxd.dracon.push
    import com.github.jonathanxd.dracon.pijulVcs
    import com.github.jonathanxd.dracon.repository.PijulRepository
    import com.github.jonathanxd.dracon.repository.PijulRepositoryManager
    import com.intellij.dvcs.push.OutgoingCommitsProvider
    import com.intellij.dvcs.push.PushSupport
    import com.intellij.dvcs.push.PushTargetPanel
    import com.intellij.dvcs.push.Pusher
    import com.intellij.dvcs.repo.RepositoryManager
    import com.intellij.openapi.components.service
    import com.intellij.openapi.project.Project
    import com.intellij.openapi.vcs.AbstractVcs
    class PijulPushSupport(val project: Project) : PushSupport<PijulRepository, PijulPushSource, PijulTarget>() {
    private val vcs = pijulVcs(project)
    override fun getVcs(): AbstractVcs = this.vcs
    override fun getPusher(): Pusher<PijulRepository, PijulPushSource, PijulTarget> =
    PijulPusher()
    override fun getOutgoingCommitsProvider(): OutgoingCommitsProvider<PijulRepository, PijulPushSource, PijulTarget> =
    PijulOutgoingChangesProvider()
    override fun getDefaultTarget(repository: PijulRepository): PijulTarget? {
    return repository.pijulConfig.defaultRemote?.let {
    PijulTarget(it, repository.currentBranchName!!)
    }
    }
    override fun getSource(repository: PijulRepository): PijulPushSource {
    return PijulPushSource(repository.currentBranchName!!)
    }
    override fun getRepositoryManager(): RepositoryManager<PijulRepository> =
    this.project.service<PijulRepositoryManager>()
    override fun createTargetPanel(
    repository: PijulRepository,
    source: PijulPushSource,
    defaultTarget: PijulTarget?
    ): PushTargetPanel<PijulTarget> =
    PijulPushTargetPanel(repository, source, defaultTarget)
    override fun isForcePushAllowed(repo: PijulRepository, target: PijulTarget?): Boolean = false
    override fun isSilentForcePushAllowed(target: PijulTarget): Boolean = false
    override fun saveSilentForcePushTarget(target: PijulTarget) {
    }
    }
  • file addition: PijulPushSource.kt (----------)
    [0.10965]
    package com.github.jonathanxd.dracon.push
    import com.intellij.dvcs.push.PushSource
    class PijulPushSource(val channel: String) : PushSource {
    override fun getPresentation(): String = this.channel
    }
  • file addition: PijulPushChanges.kt (----------)
    [0.10965]
    package com.github.jonathanxd.dracon.push
    import com.github.jonathanxd.dracon.log.Author
    import com.intellij.vcs.log.VcsUser
    import org.tomlj.Toml
    import java.io.Serializable
    import java.time.LocalDate
    import java.time.LocalDateTime
    import java.time.ZonedDateTime
    import java.time.format.DateTimeFormatter
    data class PijulPushChanges(val entries: List<PijulPushEntry>): Serializable {
    companion object {
    const val serialVersionUID = 1L
    }
    }
    data class PijulPushEntry(val hash: String,
    val dependencies: List<String>,
    val authors: List<Author>,
    // TODO: Parse date
    val date: ZonedDateTime,
    val message: String): Serializable {
    companion object {
    const val serialVersionUID = 1L
    }
    }
    fun String.parseDate(): ZonedDateTime {
    val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[.SSSSSSSSS] z")
    return ZonedDateTime.parse(this, formatter)
    }
    fun String.parsePijulPushChanges(): PijulPushChanges {
    val dependenciesPrefix = " Dependencies: "
    val authorPrefix = " Author: "
    val datePrefix = " Date: "
    val spacePrefix = " "
    val iter = this.lines().listIterator()
    val entries = mutableListOf<PijulPushEntry>()
    while (iter.hasNext()) {
    val line = iter.next()
    if (line.startsWith("#") || line.isEmpty()) {
    continue
    }
    if (line[0] != ' ') {
    val hash = line
    // Skip empty line
    iter.next()
    var next = iter.next()
    val dependencies = mutableListOf<String>()
    if (next.startsWith(dependenciesPrefix)) {
    dependencies.addAll(next.substring(dependenciesPrefix.length).split(" "))
    next = iter.next()
    }
    val authors = mutableListOf<Author>()
    if (next.startsWith(authorPrefix)) {
    val authorsToml = "authors = ${next.substring(authorPrefix.length)}"
    val toml = Toml.parse(authorsToml)
    val authorsArray = toml.getArray("authors")
    for (i in 0 until authorsArray!!.size()) {
    val authorTable = authorsArray.getTable(i)
    authors.add(
    Author(
    authorTable.getString("name"),
    authorTable.getString("full_name"),
    authorTable.getString("email")
    )
    )
    }
    next = iter.next()
    }
    val date = if (next.startsWith(datePrefix)) {
    val date = next.substring(datePrefix.length)
    next = iter.next()
    date
    } else {
    ""
    }
    val messages = mutableListOf<String>()
    if (next.trim().isEmpty()) {
    if (iter.hasNext()) {
    next = iter.next()
    while (next.startsWith(spacePrefix) || next.trim().isEmpty()) {
    messages += if (next.trim().isEmpty()) {
    ""
    } else {
    next.substring(spacePrefix.length)
    }
    if (!iter.hasNext()) break
    next = iter.next()
    }
    if (next.isNotEmpty() && next[0] != ' ') {
    iter.previous()
    }
    }
    }
    entries.add(PijulPushEntry(
    hash,
    dependencies,
    authors,
    date.parseDate(),
    messages.joinToString("\n")
    ))
    }
    }
    return PijulPushChanges(entries)
    }
  • file addition: PijulOutgoingChangesProvider.kt (----------)
    [0.10965]
    package com.github.jonathanxd.dracon.push
    import com.github.jonathanxd.dracon.changes.PijulCommittedChangeList
    import com.github.jonathanxd.dracon.context.PijulVcsContext
    import com.github.jonathanxd.dracon.i18n.DraconBundle
    import com.github.jonathanxd.dracon.pijul.SuccessStatusCode
    import com.github.jonathanxd.dracon.pijul.pijul
    import com.github.jonathanxd.dracon.repository.PijulRepository
    import com.intellij.dvcs.push.OutgoingCommitsProvider
    import com.intellij.dvcs.push.OutgoingResult
    import com.intellij.dvcs.push.PushSpec
    import com.intellij.dvcs.push.VcsError
    import com.intellij.openapi.components.service
    import com.intellij.openapi.diagnostic.Logger
    import com.intellij.vcs.log.VcsFullCommitDetails
    class PijulOutgoingChangesProvider : OutgoingCommitsProvider<PijulRepository, PijulPushSource, PijulTarget>() {
    private val logger = Logger.getInstance(PijulOutgoingChangesProvider::class.java)
    override fun getOutgoingCommits(
    repository: PijulRepository,
    pushSpec: PushSpec<PijulPushSource, PijulTarget>,
    initial: Boolean
    ): OutgoingResult {
    val project = repository.project
    val ctx = project.service<PijulVcsContext>()
    var content = ""
    val errors = mutableListOf<VcsError>()
    val fromChannel = pushSpec.source.channel
    val toChannel = pushSpec.target.channel
    val toRemote = pushSpec.target.target
    val r = pijul(project).push(project, ctx.root, fromChannel, toChannel, toRemote) {
    it.connectAndRetrieveContent()
    if (it.connected()) {
    content = it.content()
    it.write("")
    it.close()
    } else {
    errors.add(VcsError(DraconBundle.message("remote.invalid.remote.text", pushSpec.target.target)))
    content = ""
    }
    }
    if (content.isEmpty()) {
    return OutgoingResult(emptyList(), errors)
    } else {
    try {
    val parsed = content.parsePijulPushChanges()
    val commits: List<VcsFullCommitDetails> = parsed.entries.map {
    PijulVcsFullCommitDetails(
    ctx.root,
    project,
    it
    ) {
    val changes = mutableListOf<PijulCommittedChangeList>()
    pijul(project).changes(project, ctx.root, it, -1, {
    true
    }) {
    changes += it
    }
    changes.single().changes.toList()
    }
    }
    return OutgoingResult(commits, errors)
    } catch (t: Throwable) {
    logger.error(t)
    }
    }
    return OutgoingResult(emptyList(), errors)
    }
    }
    /*
    Example of changes (this is not hard to parse, but I will not do that now):
    # Please select the changes to push. The lines that contain just a
    # valid hash, and no other character (except possibly a newline), will
    # be pushed.
    ZCRW57C5MSBXYGUMGQTZNHGHO4HGHFBICW53X5I2IMGP3H2CKWRQC
    Dependencies: Q7FXTHVUPVAFMNY277C3NFJO3VXLZU5G6C6UYSD5QPURHSG3A7OQC EAGIDXOLFTHZMZ77ZWAM7MVVUBBXJMZD7RZUNBHJPYRFGGKILGVAC
    Author: [{ name = "Jonathan", full_name = "Jonathan H. R. Lopes", email = "jhrldev@gmail.com" }]
    Date: 2021-03-31 22:43:40.062881279 UTC
    Improved support for revisions
    5AUENX2YJVFNKZUSPEPDNLLL7TKZS2WTFC6CABWSZK2EC4MNCRQAC
    Dependencies: ZCRW57C5MSBXYGUMGQTZNHGHO4HGHFBICW53X5I2IMGP3H2CKWRQC
    Author: [{ name = "Jonathan", full_name = "Jonathan H. R. Lopes", email = "jhrldev@gmail.com" }]
    Date: 2021-04-01 00:07:39.373781350 UTC
    Add support to view files affected by a revision
    B43WNBLFFR2UQIH3C6KIZAQTAEQOQM3J3IYLGQMVGJHYOME73OKQC
    Dependencies: 5AUENX2YJVFNKZUSPEPDNLLL7TKZS2WTFC6CABWSZK2EC4MNCRQAC
    Author: [{ name = "Jonathan", full_name = "Jonathan H. R. Lopes", email = "jhrldev@gmail.com" }]
    Date: 2021-04-01 17:04:54.758320581 UTC
    - 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.
    Q35OTML226J2HZLHOCPV5OY6ZUM2XU4RZBE5E3GDWVHVFASHFEJAC
    Dependencies: B43WNBLFFR2UQIH3C6KIZAQTAEQOQM3J3IYLGQMVGJHYOME73OKQC
    Author: [{ name = "Jonathan", full_name = "Jonathan H. R. Lopes", email = "jhrldev@gmail.com" }]
    Date: 2021-04-02 21:31:47.581509792 UTC
    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).
    ISO7J5ZH5UB7NFZKTKKJQHQHCP4DWQ3F7SM2NDMVYJAGGIKDLX4QC
    Dependencies: Q35OTML226J2HZLHOCPV5OY6ZUM2XU4RZBE5E3GDWVHVFASHFEJAC
    Author: [{ name = "Jonathan", full_name = "Jonathan H. R. Lopes", email = "jhrldev@gmail.com" }]
    Date: 2021-04-03 03:18:36.900275901 UTC
    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.
    2N67RQZCVGL6GYJJLM2US4YVCEIUK25AHCLD66C7HR4PPTNUOCWAC
    Dependencies: ISO7J5ZH5UB7NFZKTKKJQHQHCP4DWQ3F7SM2NDMVYJAGGIKDLX4QC
    Author: [{ name = "Jonathan", full_name = "Jonathan H. R. Lopes", email = "jhrldev@gmail.com" }]
    Date: 2021-04-04 03:15:58.713132084 UTC
    Add auto installation support and cache content of ContentRevision
    37OJKSWJFDRHNWQW6P7HSZX6OWZWVNCJ2IFT42O5TANQF7VOVX6AC
    Dependencies: A7JOR7M3BUKXYMMAR43IK4GXFXGI33HM6H6LZHDES3HWW6GYFAYAC G54TB4QZZ6OYC2KZTB7KUVW3NJ6VASH7WPNFU2IATPZWM3POIRNQC 2N67RQZCVGL6GYJJLM2US4YVCEIUK25AHCLD66C7HR4PPTNUOCWAC
    Author: [{ name = "Jonathan", full_name = "Jonathan H. R. Lopes", email = "jhrldev@gmail.com" }]
    Date: 2021-04-04 12:07:50.967878750 UTC
    Improved caching code a lot
    A7IL6I3VCB3F3QMYQFPXBL33DN5XDGGQPZIBZRHYSQBSIUBBFQJQC
    Dependencies: 37OJKSWJFDRHNWQW6P7HSZX6OWZWVNCJ2IFT42O5TANQF7VOVX6AC
    Author: [{ name = "Jonathan", full_name = "Jonathan H. R. Lopes", email = "jhrldev@gmail.com" }]
    Date: 2021-04-04 18:38:01.065118605 UTC
    More files to support .ignore
    */
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/pijul/Pijul.kt at line 13
    [3.4473]
    [3.12982]
    import com.github.jonathanxd.dracon.changes.PijulCommittedChangeList
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/pijul/Pijul.kt at line 123
    [3.4137]
    [3.4856]
    @RequiresBackgroundThread
    fun push(project: Project, root: Path, editorServerConsumer: (EditorServer) -> Unit): PijulOperationResult<String>
    @RequiresBackgroundThread
    fun push(project: Project, root: Path,
    fromChannel: String? = null,
    toChannel: String? = null,
    repository: String? = null,
    editorServerConsumer: (EditorServer) -> Unit): PijulOperationResult<String>
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/pijul/Pijul.kt at line 190
    [3.4997]
    [3.22845]
    fun diff(project: Project, root: Path): PijulOperationResult<PijulLogEntry>
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/pijul/Pijul.kt at line 199
    [3.23017]
    [2.7664]
    fun changes(
    project: Project,
    root: Path,
    revision: String?,
    maxCount: Int,
    filter: (PijulLogEntry) -> Boolean,
    consumer: (PijulCommittedChangeList) -> Unit
    ): PijulOperationResult<Unit>
  • file addition: PijulHash.kt (----------)
    [3.6847]
    package com.github.jonathanxd.dracon.log
    import com.intellij.vcs.log.Hash
    class PijulHash(val hash: String) : Hash {
    override fun asString(): String = this.hash
    override fun toShortString(): String = this.hash.substring(0, 10)
    }
  • file deletion: PijulExpertRecordDialog.kt (----------)
    [3.2837][3.5830:5858](),[3.5858][3.5859:5859]()
    package com.github.jonathanxd.dracon.dialog
    import com.github.jonathanxd.dracon.completion.PijulRecordFileTextCompletionProvider
    import com.github.jonathanxd.dracon.editor.EditorServer
    import com.github.jonathanxd.dracon.i18n.DraconBundle
    import com.github.jonathanxd.dracon.pijul.NonZeroExitStatusCode
    import com.github.jonathanxd.dracon.pijul.SuccessStatusCode
    import com.github.jonathanxd.dracon.pijul.pijul
    import com.intellij.CommonBundle
    import com.intellij.ide.IdeBundle
    import com.intellij.lang.Language
    import com.intellij.notification.Notification
    import com.intellij.notification.NotificationGroup
    import com.intellij.notification.NotificationType
    import com.intellij.notification.Notifications
    import com.intellij.openapi.application.ApplicationManager
    import com.intellij.openapi.editor.Document
    import com.intellij.openapi.editor.ex.EditorEx
    import com.intellij.openapi.fileTypes.FileTypeRegistry
    import com.intellij.openapi.project.Project
    import com.intellij.openapi.ui.DialogEarthquakeShaker
    import com.intellij.openapi.ui.DialogWrapper
    import com.intellij.openapi.ui.DialogWrapper.DialogWrapperAction
    import com.intellij.openapi.ui.DialogWrapper.IdeModalityType
    import com.intellij.openapi.ui.ValidationInfo
    import com.intellij.openapi.ui.popup.JBPopupFactory
    import com.intellij.openapi.wm.IdeFocusManager
    import com.intellij.openapi.wm.WindowManager
    import com.intellij.psi.PsiFile
    import com.intellij.ui.EditorTextField
    import com.intellij.ui.LanguageTextField
    import com.intellij.ui.TextFieldWithAutoCompletion
    import com.intellij.ui.TextFieldWithAutoCompletionListProvider
    import com.intellij.util.containers.ContainerUtil
    import com.intellij.util.textCompletion.TextCompletionUtil
    import org.jetbrains.annotations.Nullable
    import java.awt.*
    import java.awt.event.*
    import java.beans.PropertyChangeEvent
    import java.beans.PropertyChangeListener
    import java.lang.Boolean
    import java.nio.file.Path
    import javax.swing.*
    open class PijulExpertRecordDialog(val project: Project,
    val vcsRoot: Path,
    val text: String) : DialogWrapper(project, true) {
    private val EXPERT_MODE_GROUP =
    NotificationGroup.createIdWithTitle("Expert Mode", DraconBundle.message("expert.mode.notification.group.id"))
    init {
    init()
    title = DraconBundle.message("action.Pijul.ExpertRecord.text")
    }
    //private lateinit var editor: EditorTextField
    //private lateinit var field: TextFieldWithAutoCompletion<String>
    private lateinit var editor: CustomEditorField
    override fun createCenterPanel(): JComponent {
    val dialogPanel = JPanel(BorderLayout())
    val tomlLanguage = Language.findLanguageByID("TOML")
    val ext = FileTypeRegistry.getInstance().getFileTypeByExtension("toml")
    val doc = LanguageTextField.createDocument(
    this.text,
    tomlLanguage,
    this.project,
    RecordDocumentCreator()
    )
    editor = CustomEditorField(tomlLanguage, project, this.text)
    /*val field = TextFieldWithAutoCompletion(this.project, Provider(), true, this.text)
    field.setOneLineMode(false)
    field.isViewer = false*/
    //editor = EditorTextField(doc, this.project, ext, false, false)
    editor.preferredSize = Dimension(800, 600)
    editor.setOneLineMode(false)
    editor.isViewer = false
    editor.isVisible = true
    editor.isEnabled = true
    //field.preferredSize = Dimension(800, 600)
    dialogPanel.add(editor, BorderLayout.CENTER)
    return dialogPanel
    }
    override fun createActions(): Array<Action> {
    return arrayOf(RecordAction(), this.cancelAction)
    }
    override fun doOKAction() {
    if (record.statusCode is SuccessStatusCode) {
    val hash = record.result!!.substring("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,
    ),
    this.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,
    ),
    this.project
    )
    super.doOKAction()
    }
    protected inner class RecordAction() : DialogWrapper.DialogWrapperAction(DraconBundle.message("expert.mode.button.record")) {
    override fun doAction(e: ActionEvent?) {
    val infoList: List<ValidationInfo> = doValidateAll()
    if (infoList.isNotEmpty()) {
    val info = infoList[0]
    if (info.component != null && info.component!!.isVisible) {
    IdeFocusManager.getInstance(null).requestFocus(info.component!!, true)
    }
    updateErrorInfo(infoList)
    startTrackingValidation()
    if (ContainerUtil.exists(
    infoList
    ) { info1: ValidationInfo -> !info1.okEnabled }
    ) return
    }
    doOKAction()
    }
    init {
    addPropertyChangeListener { evt: PropertyChangeEvent ->
    if (NAME == evt.propertyName) {
    repaint()
    }
    }
    }
    }
    class Provider : TextFieldWithAutoCompletionListProvider<String>(listOf("author", "[[authors]]", "authors", "name", "full_name", "email")) {
    override fun getLookupString(item: String): String {
    return item
    }
    }
    class RecordDocumentCreator : TextCompletionUtil.DocumentWithCompletionCreator(
    TextFieldWithAutoCompletion.StringsCompletionProvider(listOf("author", "[[authors]]", "authors", "name", "full_name", "email"),null),
    true
    )
    }
    class CustomEditorField(language: Language?, project: Project, s: String) : LanguageTextField(language, project, s, PijulExpertRecordDialog.RecordDocumentCreator(), false) {
    override fun createEditor(): EditorEx {
    val editor = super.createEditor()
    editor.setVerticalScrollbarVisible(true)
    editor.setHorizontalScrollbarVisible(true)
    editor.setCaretEnabled(true)
    editor.isViewer = false
    editor.isOneLineMode = false
    val settings = editor.settings
    settings.isLineNumbersShown = true
    settings.isAutoCodeFoldingEnabled = true
    settings.isFoldingOutlineShown = true
    settings.isAllowSingleLogicalLineFolding = true
    settings.isRightMarginShown=true
    return editor
    }
    }
    }*/
    this.editorServer.write(this.editor.text)
    this.editorServer.close()
    /*val record = pijul(this.project).recordFromString(this.project, this.vcsRoot, this.editor.text)
    val editorServer: EditorServer,
  • file addition: PijulChangesDialog.kt (----------)
    [3.2837]
    package com.github.jonathanxd.dracon.dialog
    import com.github.jonathanxd.dracon.editor.EditorServer
    import com.github.jonathanxd.dracon.i18n.DraconBundle
    import com.intellij.lang.Language
    import com.intellij.notification.NotificationGroup
    import com.intellij.openapi.editor.ex.EditorEx
    import com.intellij.openapi.fileTypes.FileTypeRegistry
    import com.intellij.openapi.project.Project
    import com.intellij.openapi.ui.DialogWrapper
    import com.intellij.openapi.ui.ValidationInfo
    import com.intellij.openapi.util.NlsContexts
    import com.intellij.openapi.util.NlsContexts.DialogTitle
    import com.intellij.openapi.util.NlsContexts.Button
    import com.intellij.openapi.wm.IdeFocusManager
    import com.intellij.ui.LanguageTextField
    import com.intellij.ui.TextFieldWithAutoCompletion
    import com.intellij.ui.TextFieldWithAutoCompletionListProvider
    import com.intellij.util.containers.ContainerUtil
    import com.intellij.util.textCompletion.TextCompletionUtil
    import java.awt.*
    import java.awt.event.*
    import java.beans.PropertyChangeEvent
    import java.nio.file.Path
    import javax.swing.*
    open class PijulChangesDialog(val project: Project,
    val vcsRoot: Path,
    val editorServer: EditorServer,
    val text: String,
    @DialogTitle val title_: String,
    @Button val button_: String) : DialogWrapper(project, true) {
    init {
    init()
    title = title_
    }
    private lateinit var editor: CustomEditorField
    override fun createCenterPanel(): JComponent {
    val dialogPanel = JPanel(BorderLayout())
    val tomlLanguage = Language.findLanguageByID("TOML")
    editor = CustomEditorField(tomlLanguage, project, this.text)
    editor.preferredSize = Dimension(800, 600)
    editor.setOneLineMode(false)
    editor.isViewer = false
    editor.isVisible = true
    editor.isEnabled = true
    dialogPanel.add(editor, BorderLayout.CENTER)
    return dialogPanel
    }
    override fun createActions(): Array<Action> {
    return arrayOf(RecordAction(), this.cancelAction)
    }
    override fun doOKAction() {
    this.editorServer.write(this.editor.text)
    this.editorServer.close()
    super.doOKAction()
    }
    protected inner class RecordAction() : DialogWrapper.DialogWrapperAction(button_) {
    override fun doAction(e: ActionEvent?) {
    val infoList: List<ValidationInfo> = doValidateAll()
    if (infoList.isNotEmpty()) {
    val info = infoList[0]
    if (info.component != null && info.component!!.isVisible) {
    IdeFocusManager.getInstance(null).requestFocus(info.component!!, true)
    }
    updateErrorInfo(infoList)
    startTrackingValidation()
    if (ContainerUtil.exists(
    infoList
    ) { info1: ValidationInfo -> !info1.okEnabled }
    ) return
    }
    doOKAction()
    }
    init {
    addPropertyChangeListener { evt: PropertyChangeEvent ->
    if (NAME == evt.propertyName) {
    repaint()
    }
    }
    }
    }
    class Provider : TextFieldWithAutoCompletionListProvider<String>(listOf("author", "[[authors]]", "authors", "name", "full_name", "email")) {
    override fun getLookupString(item: String): String {
    return item
    }
    }
    class RecordDocumentCreator : TextCompletionUtil.DocumentWithCompletionCreator(
    TextFieldWithAutoCompletion.StringsCompletionProvider(listOf("author", "[[authors]]", "authors", "name", "full_name", "email"),null),
    true
    )
    }
    class CustomEditorField(language: Language?, project: Project, s: String) : LanguageTextField(language, project, s, PijulChangesDialog.RecordDocumentCreator(), false) {
    override fun createEditor(): EditorEx {
    val editor = super.createEditor()
    editor.setVerticalScrollbarVisible(true)
    editor.setHorizontalScrollbarVisible(true)
    editor.setCaretEnabled(true)
    editor.isViewer = false
    editor.isOneLineMode = false
    val settings = editor.settings
    settings.isLineNumbersShown = true
    settings.isAutoCodeFoldingEnabled = true
    settings.isFoldingOutlineShown = true
    settings.isAllowSingleLogicalLineFolding = true
    settings.isRightMarginShown=true
    return editor
    }
    }
  • file addition: PijulConfig.kt (----------)
    [3.5365]
    package com.github.jonathanxd.dracon.config
    import com.intellij.ide.plugins.PluginManager
    import com.intellij.openapi.diagnostic.Logger
    import org.tomlj.Toml
    import java.nio.file.Files
    import java.nio.file.Path
    class PijulConfig(val root: Path) {
    private val logger = Logger.getInstance(PijulConfig::class.java)
    var currentChannel: String = ""
    var extraDependencies: List<String> = mutableListOf()
    var defaultRemote: String? = null
    var remotes: Map<String, String> = mutableMapOf()
    init {
    this.load(root)
    }
    fun load(root: Path) {
    val configPath = root.resolve(".pijul").resolve("config")
    if (!Files.exists(configPath)) {
    this.logger.error("Could not find $configPath.")
    return
    }
    val toml = Toml.parse(configPath)
    if (toml.hasErrors()) {
    this.logger.error("Errors found in .pijul/config TOML file.")
    for (error in toml.errors()) {
    this.logger.error(error)
    }
    }
    this.currentChannel = toml.getString("current_channel")!!
    val exDps = toml.getArray("extra_dependencies")!!
    this.extraDependencies = List(exDps.size()) {
    exDps.getString(it)
    }
    this.defaultRemote = toml.getString("default_remote")
    this.remotes = toml.getTable("remotes")?.toMap() as? Map<String, String> ?: emptyMap()
    }
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 16
    [3.2054]
    [3.15017]
    import com.github.jonathanxd.dracon.changes.PijulCommittedChangeList
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 19
    [3.15130]
    [3.6280]
    import com.github.jonathanxd.dracon.content.PijulContentRevision
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 30
    [3.2779]
    [3.4157]
    import com.github.jonathanxd.dracon.pijulVcs
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 41
    [3.2835]
    [3.11522]
    import com.intellij.openapi.vcs.changes.Change
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 44
    [3.11640]
    [3.6896]
    import com.intellij.util.text.trimMiddle
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 136
    [3.8371][3.8371:8407]()
    } catch(t: Throwable) {
    [3.8371]
    [3.8407]
    } catch (t: Throwable) {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 143
    [3.9353][3.9353:9494](),[3.9494][3.8650:8696](),[3.15858][3.8650:8696](),[3.8650][3.8650:8696]()
    this.doExecutionWithMapper("file_status_from_ls", this.createExecPijulOperation(project, rootPath, listOf("ls"), log = false)) {
    val trackedFiles = it.split("\n")
    [3.9353]
    [3.3474]
    this.doExecutionWithMapper(
    "file_status_from_ls",
    this.createExecPijulOperation(project, rootPath, listOf("ls"), log = false)
    ) {
    val trackedFiles = it.split("\n")
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 149
    [3.3475][3.3475:3578](),[3.3578][3.8697:8784](),[3.8784][3.3651:3672](),[3.3651][3.3651:3672](),[3.3672][3.8298:8333]()
    val fPath = Paths.get(VcsUtil.getFilePath(file.path).path).relativeTo(rootPath).toString()
    if (trackedFiles.contains(fPath)) {
    FileStatus.NOT_CHANGED
    } else {
    FileStatus.UNKNOWN
    [3.3475]
    [3.8806]
    val fPath = Paths.get(VcsUtil.getFilePath(file.path).path).relativeTo(rootPath).toString()
    if (trackedFiles.contains(fPath)) {
    FileStatus.NOT_CHANGED
    } else {
    FileStatus.UNKNOWN
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 156
    [3.8820][3.8820:8830]()
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 159
    [3.8967][3.8967:9044]()
    || fileStatusBasedInPijulDiff.result == FileStatus.SUPPRESSED) {
    [3.8967]
    [3.9044]
    || fileStatusBasedInPijulDiff.result == FileStatus.SUPPRESSED
    ) {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 185
    [3.10307][3.10307:10343]()
    } catch(t: Throwable) {
    [3.10307]
    [3.10343]
    } catch (t: Throwable) {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 192
    [3.10472][3.10472:10609]()
    this.doExecutionWithMapper("file_status_from_ls", this.createExecPijulOperation(project, root, listOf("ls"), log = false)) {
    [3.10472]
    [3.10609]
    this.doExecutionWithMapper(
    "file_status_from_ls",
    this.createExecPijulOperation(project, root, listOf("ls"), log = false)
    ) {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 208
    [3.11049][3.11049:11126]()
    || fileStatusBasedInPijulDiff.result == FileStatus.SUPPRESSED) {
    [3.11049]
    [3.11126]
    || fileStatusBasedInPijulDiff.result == FileStatus.SUPPRESSED
    ) {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 220
    [3.25385][3.25385:25443]()
    val credit = this.doExecutionWithMapper("credit",
    [3.25385]
    [3.25443]
    val credit = this.doExecutionWithMapper(
    "credit",
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 254
    [3.11954][3.11954:11990]()
    } catch(t: Throwable) {
    [3.11954]
    [3.11990]
    } catch (t: Throwable) {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 261
    [3.12119][3.12119:12256]()
    this.doExecutionWithMapper("file_status_from_ls", this.createExecPijulOperation(project, root, listOf("ls"), log = false)) {
    [3.12119]
    [3.12256]
    this.doExecutionWithMapper(
    "file_status_from_ls",
    this.createExecPijulOperation(project, root, listOf("ls"), log = false)
    ) {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 282
    [3.25792][3.25792:26026]()
    return this.doExecutionWithMapper("tracked_files_from_ls", this.createExecPijulOperation(project, root, listOf("ls"), log = false)) {
    it.split("\n").map {
    root.resolve(it)
    }
    [3.25792]
    [3.26026]
    return this.doExecutionWithMapper(
    "tracked_files_from_ls",
    this.createExecPijulOperation(project, root, listOf("ls"), log = false)
    ) {
    it.split("\n").map {
    root.resolve(it)
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 289
    [3.26040]
    [3.26040]
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 305
    [3.9729][3.9729:9872]()
    return PijulOperationResult("rollbackTo_${hash}", NonZeroExitStatusCode(-1, "Could not find hash $hash in Pijul log."), false)
    [3.9729]
    [3.9872]
    return PijulOperationResult(
    "rollbackTo_${hash}",
    NonZeroExitStatusCode(-1, "Could not find hash $hash in Pijul log."),
    false
    )
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 381
    [3.7747][3.7747:7871]()
    return this.doExecutionWithMapper("record", this.createPainlessExecPijulOperation(this.project, root, arguments)) {
    [3.7747]
    [3.7871]
    return this.doExecutionWithMapper(
    "record",
    this.createPainlessExecPijulOperation(this.project, root, arguments)
    ) {
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 426
    [3.8807]
    [3.8807]
    it
    }
    }
    override fun push(
    project: Project,
    root: Path,
    editorServerConsumer: (EditorServer) -> Unit
    ): PijulOperationResult<String> {
    val arguments = mutableListOf("push")
    val operation = this.createPainlessExecPijulWithEditorServer(
    this.project,
    root,
    arguments,
    editorServerConsumer
    )
    return this.doExecutionWithMapper("push", operation) {
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 448
    [3.7185]
    [3.7185]
    override fun push(
    project: Project,
    root: Path,
    fromChannel: String?,
    toChannel: String?,
    repository: String?,
    editorServerConsumer: (EditorServer) -> Unit
    ): PijulOperationResult<String> {
    val arguments = mutableListOf("push")
    if (fromChannel != null) {
    arguments.add("--from-channel")
    arguments.add(fromChannel)
    }
    if (toChannel != null) {
    arguments.add("--to-channel")
    arguments.add(toChannel)
    }
    if (repository != null) {
    arguments.add(repository)
    }
    val operation = this.createPainlessExecPijulWithEditorServer(
    this.project,
    root,
    arguments,
    editorServerConsumer
    )
    return this.doExecutionWithMapper("push", operation) {
    it
    }
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 566
    [3.13387][3.2389:2452](),[3.2389][3.2389:2452]()
    this.doExecutionWithMapper("change-$hash",
    [3.13387]
    [3.2452]
    this.doExecutionWithMapper(
    "change-$hash",
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 633
    [3.13454][3.2721:2784](),[3.2721][3.2721:2784]()
    this.doExecutionWithMapper("change-$hash",
    [3.13454]
    [3.2784]
    this.doExecutionWithMapper(
    "change-$hash",
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 688
    [3.18976]
    [3.18976]
    }
    override fun changes(
    project: Project,
    root: Path,
    revision: String?,
    maxCount: Int,
    filter: (PijulLogEntry) -> Boolean,
    consumer: (PijulCommittedChangeList) -> Unit
    ): PijulOperationResult<Unit> {
    val allRevisions = pijul(this.project).allRevisions(this.project, root).result!!
    val log = this.log(this.project, root)
    return log.result?.entries?.filter {
    filter(it)
    }?.filter {
    revision == null || it.revision.hash == revision
    }?.map { entry ->
    PijulCommittedChangeList(
    entry.message.trimMiddle(20),
    entry.message,
    entry.authors.firstOrNull()?.name ?: "No author",
    Date.from(entry.date.toInstant()),
    entry.hunks.filterIsInstance<HunkWithPath>().groupBy { it.resolvePath(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()
    val beforeRevision =
    if (hunk is FileAddHunk) null
    else findARevisionBefore(entry.changeHash, allRevisions)?.let {
    PijulContentRevision(
    root,
    hunk.resolvePath(root),
    it,
    this.project
    )
    }
    val afterRevision =
    if (hunk is FileDelHunk) null
    else PijulContentRevision(
    root,
    hunk.resolvePath(root),
    entry.revision,
    this.project
    )
    Change(
    beforeRevision,
    afterRevision,
    hunk.status
    )
    }.toMutableList(),
    entry.revision,
    false,
    pijulVcs(this.project)
    )
    }?.let { if (maxCount == -1) it else it.take(maxCount) }?.forEach {
    consumer(it)
    }?.let {
    PijulOperationResult("changes", SuccessStatusCode, Unit)
    } ?: PijulOperationResult("changes", log.statusCode, Unit)
    }
    fun findARevisionBefore(current: String, allRevisions: List<PijulRevisionNumber>): PijulRevisionNumber? {
    for (i in allRevisions.indices) {
    if (current == allRevisions[i].hash) {
    return if (i + 1 >= allRevisions.size) {
    null
    } else {
    allRevisions[i + 1]
    }
    }
    }
    return null
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 775
    [3.11387][3.13455:13579]()
    val change = this.doExecutionWithMapper("diff", this.createExecPijulOperation(project, rootPath, listOf("diff"))) {
    [3.11387]
    [3.11509]
    val change =
    this.doExecutionWithMapper("diff", this.createExecPijulOperation(project, rootPath, listOf("diff"))) {
    if (it.isEmpty()) null
    else it.parseChange("")
    }
    return change
    }
    override fun diff(project: Project, root: Path): PijulOperationResult<PijulLogEntry> {
    val change = this.doExecutionWithMapper("diff", this.createExecPijulOperation(project, root, listOf("diff"))) {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 874
    [3.3762][3.3762:3971]()
    fun <T> doExecutionWithMapper(name: String,
    execution: PijulExecution,
    regularStreamStringMapper: (String) -> T?): PijulOperationResult<T> {
    [3.3762]
    [3.3182]
    fun <T> doExecutionWithMapper(
    name: String,
    execution: PijulExecution,
    regularStreamStringMapper: (String) -> T?
    ): PijulOperationResult<T> {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 892
    [3.9284][3.9284:9507]()
    fun <T> doExecutionWithMapperEvenFailed(name: String,
    execution: PijulExecution,
    regularStreamStringMapper: (String) -> T?): PijulOperationResult<T> {
    [3.9284]
    [3.3315]
    fun <T> doExecutionWithMapperEvenFailed(
    name: String,
    execution: PijulExecution,
    regularStreamStringMapper: (String) -> T?
    ): PijulOperationResult<T> {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 924
    [3.14313][3.20920:21092](),[3.21092][3.13580:13660]()
    private fun createExecPijulOperation(project: Project,
    dir: Path,
    args: List<String>,
    log: Boolean = true): PijulExecution {
    [3.14313]
    [3.14458]
    private fun createExecPijulOperation(
    project: Project,
    dir: Path,
    args: List<String>,
    log: Boolean = true
    ): PijulExecution {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 977
    [3.22008][3.22008:22075](),[3.22075][3.10126:10273]()
    private fun createPainlessExecPijulOperation(project: Project,
    dir: Path,
    args: List<String>): PijulExecution {
    [3.22008]
    [3.10273]
    private fun createPainlessExecPijulOperation(
    project: Project,
    dir: Path,
    args: List<String>
    ): PijulExecution {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 1025
    [3.5791][3.5791:6134]()
    private fun <K: Any> createPainlessExecPijulOperationWithCache(project: Project,
    dir: Path,
    args: List<String>,
    key: K): PijulExecution {
    [3.5791]
    [3.6134]
    private fun <K : Any> createPainlessExecPijulOperationWithCache(
    project: Project,
    dir: Path,
    args: List<String>,
    key: K
    ): PijulExecution {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 1076
    [3.12106][3.12106:12502]()
    private fun createPainlessExecPijulWithCopieOperation(project: Project,
    dir: Path,
    copiePath: Path,
    copieMode: CopieMode,
    args: List<String>): PijulExecution {
    [3.12106]
    [3.22206]
    private fun createPainlessExecPijulWithCopieOperation(
    project: Project,
    dir: Path,
    copiePath: Path,
    copieMode: CopieMode,
    args: List<String>
    ): PijulExecution {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 1085
    [3.12524][3.12524:12558]()
    when(copieMode) {
    [3.12524]
    [3.12558]
    when (copieMode) {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 1136
    [3.9657][3.9657:9994]()
    private fun createPainlessExecPijulWithEditorServer(project: Project,
    dir: Path,
    args: List<String>,
    editorServerConsumer: (EditorServer) -> Unit): PijulExecution {
    [3.9657]
    [3.9994]
    private fun createPainlessExecPijulWithEditorServer(
    project: Project,
    dir: Path,
    args: List<String>,
    editorServerConsumer: (EditorServer) -> Unit
    ): PijulExecution {
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 4
    [3.19908][3.19908:19973]()
    import com.github.jonathanxd.dracon.content.PijulContentRevision
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 5
    [3.20033][3.20033:20075]()
    import com.github.jonathanxd.dracon.log.*
    [3.20033]
    [3.20075]
    import com.github.jonathanxd.dracon.log.PijulLogEntry
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 7
    [3.20123][3.20123:20168]()
    import com.github.jonathanxd.dracon.pijulVcs
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 21
    [3.21126][3.11416:11457]()
    import com.intellij.util.text.trimMiddle
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 30
    [3.21490][3.21490:21621]()
    class PijulCommittedChangesProvider(val project: Project) : CommittedChangesProvider<CommittedChangeList, ChangeBrowserSettings> {
    [3.21490]
    [3.21621]
    class PijulCommittedChangesProvider(val project: Project) :
    CommittedChangesProvider<CommittedChangeList, ChangeBrowserSettings> {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 37
    [3.21914][3.21914:22052]()
    val channel = pijul(this.project).channel(this.project, ctx.root).result?.channels?.firstOrNull { it.current }?.name ?: "unknown"
    [3.21914]
    [3.22052]
    val channel =
    pijul(this.project).channel(this.project, ctx.root).result?.channels?.firstOrNull { it.current }?.name
    ?: "unknown"
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 117
    [3.24245][3.24245:24421]()
    val allRevisions = pijul(this.project).allRevisions(this.project, ctx.root).result!!
    pijul(this.project).log(this.project, ctx.root).result?.entries?.filter {
    [3.24245]
    [3.24421]
    pijul(this.project).changes(this.project, ctx.root, revision?.asString(), maxCount, {
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 119
    [3.24470][3.11750:11842](),[3.11842][3.24470:24534](),[3.24470][3.24470:24534](),[3.24534][3.11843:11889](),[3.11889][3.24534:24565](),[3.24534][3.24534:24565](),[3.24585][3.24585:24702](),[3.24702][3.13964:14397](),[3.14397][3.24777:25985](),[3.24777][3.24777:25985]()
    }?.filter {
    revision == null || it.revision.hash == revision.asString()
    }?.map { entry ->
    PijulCommittedChangeList(
    entry.message.trimMiddle(20),
    entry.message,
    entry.authors.firstOrNull()?.name ?: "No author",
    Date.from(entry.date.toInstant()),
    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()
    val beforeRevision =
    if (hunk is FileAddHunk) null
    else findARevisionBefore(entry.changeHash, allRevisions)?.let {
    PijulContentRevision(
    ctx.root,
    hunk.resolvePath(ctx.root),
    it,
    this.project
    )
    }
    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)
    )
    }?.let { if (maxCount == -1) it else it.take(maxCount) }?.forEach {
    [3.24470]
    [3.25985]
    }) {
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 125
    [3.26028][3.26028:26231](),[3.26231][3.11890:11947](),[3.11947][3.26268:26318](),[3.26268][3.26268:26318](),[3.26318][3.11948:11988](),[3.11988][3.26358:26428](),[3.26358][3.26358:26428]()
    fun findARevisionBefore(current: String, allRevisions: List<PijulRevisionNumber>): PijulRevisionNumber? {
    for (i in allRevisions.indices) {
    if (current == allRevisions[i].hash) {
    return if (i + 1 >= allRevisions.size) {
    null
    } else {
    allRevisions[i + 1]
    }
    }
    }
    return null
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cache/FileRevisionCache.kt at line 10
    [3.20486]
    [3.30088]
    import com.intellij.openapi.progress.EmptyProgressIndicator
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cache/FileRevisionCache.kt at line 33
    [3.21078][3.21078:21165](),[3.21165][3.30884:30910](),[3.30910][3.21200:21230](),[3.21200][3.21200:21230]()
    return this.cache.queryOrLoadAsync(fileRev) {
    loadStateInRevision(
    rev.hash,
    this.project,
    [3.21078]
    [3.21230]
    return this.cache.queryOrLoadAsyncExpanded(fileRev) {
    val revisions = loadStateInEveryRevisionForAllFiles(
    listOf(rev.hash),
    project,
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cache/FileRevisionCache.kt at line 38
    [3.21252][3.30911:30932](),[3.30932][3.21281:21323](),[3.21281][3.21281:21323]()
    file
    ).toByteArray(Charsets.UTF_8)
    [3.21252]
    [3.21323]
    EmptyProgressIndicator()
    )
    val revisionsForHash = revisions[rev.hash]!!
    val stringKeys = revisionsForHash.mapKeys { (k, _) -> k.filePathAsString() }
    stringKeys[it.filePath]!! to stringKeys.map { (k, v) -> FileRevisionRef(k, rev.hash) to v }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cache/DataCache.kt at line 32
    [3.22376][3.33001:33067]()
    private val updateExecutor = Executors.newFixedThreadPool(10)
    [3.22376]
    [3.22441]
    private val updateExecutor = Executors.newWorkStealingPool(16)
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cache/DataCache.kt at line 110
    [3.33538]
    [3.24508]
    this.inMemory[key] = computeEntry
    this.manager.write(this.inMemory)
    computeEntry
    } finally {
    this.lock.unlock()
    }.value
    }, this.updateExecutor)
    }
    }
    fun queryOrLoadAsyncExpanded(key: K, compute: (K) -> Pair<V, List<Pair<K, V>>>): CompletableFuture<V> {
    if (this.inMemory.containsKey(key)) {
    return CompletableFuture.completedFuture(this.inMemory[key]!!.value)
    } else {
    return CompletableFuture.supplyAsync({
    this.lock.lock()
    try {
    if (this.inMemory.containsKey(key)) {
    return@supplyAsync this.inMemory[key]!!.value
    }
    val instant = Instant.now()
    val computed = compute(key)
    val computeEntry = CachedValue(instant, computed.first)
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cache/DataCache.kt at line 137
    [3.24563]
    [3.24563]
    computed.second.forEach { (k, v) ->
    this.inMemory[k] = CachedValue(instant, v)
    }
  • file addition: PijulPushRecord.kt (----------)
    [3.18106]
    package com.github.jonathanxd.dracon.actions
    import com.github.jonathanxd.dracon.dialog.PijulChangesDialog
    import com.github.jonathanxd.dracon.i18n.DraconBundle
    import com.github.jonathanxd.dracon.pijul.NonZeroExitStatusCode
    import com.github.jonathanxd.dracon.pijul.SuccessStatusCode
    import com.github.jonathanxd.dracon.pijul.pijul
    import com.intellij.notification.Notification
    import com.intellij.notification.NotificationGroup
    import com.intellij.notification.NotificationType
    import com.intellij.notification.Notifications
    import com.intellij.openapi.actionSystem.AnActionEvent
    import com.intellij.openapi.project.DumbAwareAction
    import com.intellij.openapi.vcs.ProjectLevelVcsManager
    class PijulPushRecord : DumbAwareAction() {
    private val PUSH_GROUP =
    NotificationGroup.createIdWithTitle("Push Changes", DraconBundle.message("push.notification.group.id"))
    override fun actionPerformed(e: AnActionEvent) {
    val project = e.project!!
    val vcsManager = ProjectLevelVcsManager.getInstance(project)
    val root = vcsManager.allVcsRoots.first().path.toNioPath()
    val record = pijul(project).push(project, root) {
    it.connectAndRetrieveContent()
    if (it.connected()) {
    PijulChangesDialog(project, root, it, it.content(),
    DraconBundle.message("action.Pijul.Push.text"),
    DraconBundle.message("push.button.text")).showAndGet()
    }
    }
    if (record.statusCode is SuccessStatusCode) {
    Notifications.Bus.notify(
    Notification(
    PUSH_GROUP,
    DraconBundle.message("push.notification.title"),
    DraconBundle.message("push.notification.success"),
    NotificationType.ERROR,
    ),
    project
    )
    } else {
    record.statusCode as NonZeroExitStatusCode
    Notifications.Bus.notify(
    Notification(
    PUSH_GROUP,
    DraconBundle.message("push.notification.title"),
    DraconBundle.message("push.notification.failure", record.statusCode.exitCode, record.statusCode.message),
    NotificationType.INFORMATION,
    ),
    project
    )
    }
    }
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/actions/PijulExpertRecord.kt at line 3
    [3.30201][3.30201:30335]()
    import com.github.jonathanxd.dracon.dialog.PijulExpertRecordDialog
    import com.github.jonathanxd.dracon.dialog.createPijulRecordDialog
    [3.30201]
    [3.12206]
    import com.github.jonathanxd.dracon.dialog.PijulChangesDialog
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/actions/PijulExpertRecord.kt at line 13
    [3.30438][3.30438:30608]()
    import com.intellij.openapi.fileEditor.FileEditorManager
    import com.intellij.openapi.fileEditor.OpenFileDescriptor
    import com.intellij.openapi.fileTypes.FileTypeRegistry
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/actions/PijulExpertRecord.kt at line 15
    [3.30715][3.30715:30835]()
    import com.intellij.testFramework.LightVirtualFile
    import com.intellij.ui.layout.panel
    import kotlin.io.path.relativeTo
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/actions/PijulExpertRecord.kt at line 24
    [3.31105][3.31105:31177]()
    val recordString = pijul(project).recordToString(project, root)
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/actions/PijulExpertRecord.kt at line 29
    [3.12875][3.12875:12961]()
    PijulExpertRecordDialog(project, root, it, it.content()).showAndGet()
    [3.12875]
    [3.12961]
    PijulChangesDialog(project, root, it, it.content(),
    DraconBundle.message("action.Pijul.ExpertRecord.text"),
    DraconBundle.message("expert.mode.button.record")).showAndGet()
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/actions/PijulExpertRecord.kt at line 59
    [3.14043][3.14043:14089](),[3.14089][3.31221:31386](),[3.31221][3.31221:31386](),[3.31386][3.14090:14107](),[3.14107][3.31401:31963](),[3.31401][3.31401:31963](),[3.31963][3.14108:14126](),[3.14126][3.31979:32067](),[3.31979][3.31979:32067](),[3.32067][3.14127:14198](),[3.14198][3.32136:32257](),[3.32136][3.32136:32257](),[3.32257][3.14199:14229]()
    /*if (recordString.result != null) {
    val toml = FileTypeRegistry.getInstance().getFileTypeByExtension("toml")
    //val editor = EditorTextField(recordString.result, this.project, )
    *//*
    val psiFile = PsiDocumentManager.getInstance(editor.getProject()).getPsiFile(editor.getDocument())
    val element = psiFile!!.findElementAt(editor.getCaretModel().getOffset())
    val code: PsiExpressionCodeFragment = JavaCodeFragmentFactory.getInstance(editor.getProject())
    .createExpressionCodeFragment("", element, null, true)
    val document: Document? = PsiDocumentManager.getInstance(editor.getProject()).getDocument(code)
    val myInput = EditorTextField(document, editor.getProject(), JavaFileType.INSTANCE)
    *//*
    PijulExpertRecordDialog(project, root, recordString.result).showAndGet()
    *//*FileEditorManager.getInstance(project).openTextEditor(
    OpenFileDescriptor(project, LightVirtualFile("record", toml, recordString.result)),
    true
    )*//*
    }*/
  • edit in build.gradle.kts at line 66
    [18.15461]
    [18.15461]
  • edit in build.gradle.kts at line 98
    [18.16175]
    [18.16175]
    withType<org.jetbrains.intellij.tasks.RunIdeTask> {
    this.maxHeapSize = "2G"
    }