Fork channel

Create a new channel as a copy of main.

Rename channel

Rename main to:

Delete channel

Delete main? This cannot be undone.

DraconTest.kt
/**
 * Dracon - An IntelliJ-Pijul integration.
 * Copyright 2021 JonathanxD <jhrldev@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package com.github.jonathanxd.dracon.test

import com.github.jonathanxd.dracon.log.*
import io.kotest.core.spec.style.ShouldSpec
import io.kotest.matchers.shouldBe
import java.time.ZoneOffset
import java.time.ZonedDateTime

class DraconTest : ShouldSpec({
    should("correctly parse a 'pijul change' text without authors") {
        val text = """
            message = 'Initial ChangeProvider'
            timestamp = '2021-03-29T01:50:38.537749028Z'
            
        """.trimIndent()

        val change = text.parseChange("DRACON")

        change.changeHash shouldBe "DRACON"
        change.message shouldBe "Initial ChangeProvider"
        change.date shouldBe ZonedDateTime.of(2021, 3, 29, 1, 50, 38, 537749028, ZoneOffset.UTC)
    }

    should("correctly parse a 'pijul change' text with single author") {
        val text = """
            message = 'Initial ChangeProvider'
            timestamp = '2021-03-29T01:50:38.537749028Z'

            [[authors]]
            name = 'Author'
        """.trimIndent()

        val change = text.parseChange("DRACON")

        change.changeHash shouldBe "DRACON"
        change.message shouldBe "Initial ChangeProvider"
        change.authors.isEmpty() shouldBe false
        change.authors[0].name shouldBe "Author"
        change.date shouldBe ZonedDateTime.of(2021, 3, 29, 1, 50, 38, 537749028, ZoneOffset.UTC)
    }

    should("correctly parse a 'pijul change' text with two authors") {
        val text = """
            message = 'Initial ChangeProvider'
            timestamp = '2021-03-29T01:50:38.537749028Z'

            [[authors]]
            name = 'Author1'
            name = 'Author2'
        """.trimIndent()

        val change = text.parseChange("DRACON")

        change.changeHash shouldBe "DRACON"
        change.message shouldBe "Initial ChangeProvider"
        change.authors.size shouldBe 2
        change.authors[0].name shouldBe "Author1"
        change.authors[1].name shouldBe "Author2"
        change.date shouldBe ZonedDateTime.of(2021, 3, 29, 1, 50, 38, 537749028, ZoneOffset.UTC)
    }

    should("correctly parse a 'pijul change' text with three authors and dependencies") {
        val text = """
            message = 'Initial ChangeProvider'
            timestamp = '2021-03-29T01:50:38.537749028Z'

            [[authors]]
            name = 'Author1'
            name = 'Author2'
            name = 'Author3'
                      
            # Dependencies
            [2] PGNTR2EPCZBOWI67LKY6AN5B3RGIEOQ6NTTXGODLESKDSPWV26KQC
            [3]+FNNW5IEAXQ43WKB6QSQB7DFLG3Y3T5FYPXIUX7KQ2URR2GU3QLTAC
            [4]+OPFG6CZ26PPTGTH7ULLRQGZGR3YEIEJOV5W2E3WN7PFRZS62CVLQC
            [5]+GGYFPXND4VBCROZZXTKAP7Y4JOP2OOYQAFVLMUE7SLFM225EUSIAC
            [*] NTRPUMVQHUIQZ6O72NJ72XFYTZWZOSDA6CSKMUCGKFVNE3KIDYYQC
        """.trimIndent()

        val change = text.parseChange("DRACON")

        change.changeHash shouldBe "DRACON"
        change.message shouldBe "Initial ChangeProvider"
        change.authors.size shouldBe 3
        change.authors[0].name shouldBe "Author1"
        change.authors[1].name shouldBe "Author2"
        change.authors[2].name shouldBe "Author3"
        change.date shouldBe ZonedDateTime.of(2021, 3, 29, 1, 50, 38, 537749028, ZoneOffset.UTC)
        change.dependencies.size shouldBe 5
        change.dependencies[0] shouldBe Dependency(
            IndexInt(2),
            DependencyType.REGULAR_DEPENDENCY,
            "PGNTR2EPCZBOWI67LKY6AN5B3RGIEOQ6NTTXGODLESKDSPWV26KQC"
        )
        change.dependencies[1] shouldBe Dependency(
            IndexInt(3),
            DependencyType.CHANGE_DEPENDENCY,
            "FNNW5IEAXQ43WKB6QSQB7DFLG3Y3T5FYPXIUX7KQ2URR2GU3QLTAC"
        )
        change.dependencies[2] shouldBe Dependency(
            IndexInt(4),
            DependencyType.CHANGE_DEPENDENCY,
            "OPFG6CZ26PPTGTH7ULLRQGZGR3YEIEJOV5W2E3WN7PFRZS62CVLQC"
        )
        change.dependencies[3] shouldBe Dependency(
            IndexInt(5),
            DependencyType.CHANGE_DEPENDENCY,
            "GGYFPXND4VBCROZZXTKAP7Y4JOP2OOYQAFVLMUE7SLFM225EUSIAC"
        )
        change.dependencies[4] shouldBe Dependency(
            Asterisk,
            DependencyType.EXTRA_KNOWN_DEPENDENCY,
            "NTRPUMVQHUIQZ6O72NJ72XFYTZWZOSDA6CSKMUCGKFVNE3KIDYYQC"
        )
    }

    should("correctly parse a 'pijul change' text with example change") {
        val text = """
message = 'Initial ChangeProvider'
timestamp = '2021-03-29T01:50:38.537749028Z'

[[authors]]
name = 'Author1'

# Dependencies
[2] PGNTR2EPCZBOWI67LKY6AN5B3RGIEOQ6NTTXGODLESKDSPWV26KQC # Improved README and ider roadmap
[3]+FNNW5IEAXQ43WKB6QSQB7DFLG3Y3T5FYPXIUX7KQ2URR2GU3QLTAC # Added more plugin files to Pijul
[4]+OPFG6CZ26PPTGTH7ULLRQGZGR3YEIEJOV5W2E3WN7PFRZS62CVLQC # File status tracking supported.
[5]+GGYFPXND4VBCROZZXTKAP7Y4JOP2OOYQAFVLMUE7SLFM225EUSIAC # Initial plugin
[*] NTRPUMVQHUIQZ6O72NJ72XFYTZWZOSDA6CSKMUCGKFVNE3KIDYYQC # Improved README and added roadmap.

# Hunks

1. File addition: "revision" in "src/main/kotlin/com/github/jonathanxd/dracon" +dx "UTF-8"
  up 3.107, new 0:10

2. File addition: "PijulRevisionNumber.kt" in "src/main/kotlin/com/github/jonathanxd/dracon/revision" "UTF-8"
  up 0.11, new 12:36
+ package com.github.jonathanxd.dracon.revision
+ 
+ import com.intellij.openapi.vcs.changes.patch.BlobIndexUtil
+ import com.intellij.openapi.vcs.history.ShortVcsRevisionNumber
+ import com.intellij.openapi.vcs.history.VcsRevisionNumber
+ import java.time.LocalDateTime
+ import java.time.ZonedDateTime
+ 
+ class PijulRevisionNumber(val hash: String, val timestamp: ZonedDateTime) : ShortVcsRevisionNumber {
+ 
+     val NOT_COMMITTED_HASH = BlobIndexUtil.NOT_COMMITTED_HASH
+ 
+     override fun compareTo(other: VcsRevisionNumber): Int {
+         if (this === other) return 0
+ 
+         if (other is PijulRevisionNumber) {
+             return this.timestamp.compareTo(other.timestamp)
+         }
+ 
+         return -1
+     }
+ 
+     override fun asString(): String = this.hash
+ 
+     override fun toShortString(): String = this.asString()
+ }
\

3. File addition: "provider" in "src/main/kotlin/com/github/jonathanxd/dracon" +dx "UTF-8"
  up 3.107, new 843:853

4. File addition: "PijulChangeProvider.kt" in "src/main/kotlin/com/github/jonathanxd/dracon/provider" "UTF-8"
  up 0.854, new 855:879
+ package com.github.jonathanxd.dracon.provider
+ 
+ import com.intellij.openapi.progress.ProgressIndicator
+ import com.intellij.openapi.project.Project
+ import com.intellij.openapi.vcs.VcsKey
+ import com.intellij.openapi.vcs.changes.*
+ 
+ class PijulChangeProvider(val project: Project, val key: VcsKey) : ChangeProvider {
+     override fun getChanges(
+         dirtyScope: VcsDirtyScope,
+         builder: ChangelistBuilder,
+         progress: ProgressIndicator,
+         addGate: ChangeListManagerGate
+     ) {
+         if (project.isDisposed) return
+         val dirtDirs = dirtyScope.recursivelyDirtyDirectories
+ 
+         println(dirtDirs)
+     }
+ 
+     override fun isModifiedDocumentTrackingRequired(): Boolean = true
+ }
\

5. Edit in "src/main/kotlin/com/github/jonathanxd/dracon/pijul/Pijul.kt":13 3.4428 "UTF-8"
  up 3.4473, new 1584:1698, down 3.4473
+ import com.github.jonathanxd.dracon.log.PijulLog
+ import com.github.jonathanxd.dracon.revision.PijulRevisionNumber

6. Edit in "src/main/kotlin/com/github/jonathanxd/dracon/pijul/Pijul.kt":82 3.4428 "UTF-8"
  up 3.6839, new 1699:1950, down 3.6839
+     @RequiresBackgroundThread
+     fun latestRevisionNumber(project: Project, root: VirtualFile): PijulOperationResult<PijulRevisionNumber>
+ 
+     @RequiresBackgroundThread
+     fun log(project: Project, root: VirtualFile): PijulOperationResult<PijulLog>

7. File addition: "PijulLog.kt" in "src/main/kotlin/com/github/jonathanxd/dracon/log" "UTF-8"
  up 3.6847, new 1951:1964
+ package com.github.jonathanxd.dracon.log
+ 
+ import java.time.LocalDateTime
+ import java.time.ZonedDateTime
+ import java.time.format.DateTimeFormatter
+ import java.time.format.ResolverStyle
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ class Author(val name: String?, val fullName: String?, val email: String?)
+ class PijulLog(val entries: List<PijulLogEntry>)
+ 
+ class PijulLogEntry(
+     val changeHash: String,
+                     val message: String,
+                     val date: ZonedDateTime,
+                     val authors: List<Author>
+ )
+ 
+ 
+ val MESSAGE_PATTERN = Regex("message = '(.*)'\\n")
+ val TIME_PATTERN = Regex("timestamp = '(.*)'\\n")
+ val AUTHORS_SECTION_PATTERN = Regex("\\[\\[authors\\]\\]\n")
+ val AUTHOR_PATTERN = Regex("name = '(.*)'\\n")
+ 
+ fun String.parseChange(hash: String): PijulLogEntry {
+     val message = MESSAGE_PATTERN.find(this)?.groupValues?.get(1)!!
+     val timestamp = TIME_PATTERN.find(this)?.groupValues?.get(1)!!
+     val authorsSection = AUTHORS_SECTION_PATTERN.find(this)?.range?.endInclusive
+     val authors = mutableListOf<Author>()
+ 
+     if (authorsSection != null) {
+ 
+         var lastFound: Int? = authorsSection
+         while (lastFound != null) {
+             val foundAuthor = AUTHOR_PATTERN.find(this, lastFound)
+             val foundAuthorGroup = foundAuthor?.groupValues?.get(1)
+ 
+             if (foundAuthorGroup != null) {
+                 authors += Author(foundAuthorGroup, null, null)
+                 lastFound = if (foundAuthor.range.last + 1 < this.length && this[foundAuthor.range.last + 1] == '\n') {
+                     null
+                 } else {
+                     foundAuthor.range.last
+                 }
+             } else {
+                 lastFound = null
+             }
+         }
+     }
+ 
+     return PijulLogEntry(hash, message, timestamp.parseAsLocalDateTime(), authors)
+ }
+ 
+ val RFC3339_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSSSSSSSS]XXX")
+     .withResolverStyle(ResolverStyle.LENIENT)
+ 
+ fun String.parseAsLocalDateTime(): ZonedDateTime {
+     return ZonedDateTime.parse(this, RFC3339_FORMATTER)
+ }
\

8. Edit in "src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt":13 3.10972 "UTF-8"
  up 3.11015, new 4000:4103, down 3.11015
+ import com.github.jonathanxd.dracon.log.PijulLog
+ import com.github.jonathanxd.dracon.log.PijulLogEntry

9. Edit in "src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt":16 3.10972 "UTF-8"
  up 3.11075, new 4104:4156, down 3.11075
+ import com.github.jonathanxd.dracon.log.parseChange

10. Edit in "src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt":20 3.10972 "UTF-8"
  up 4.2779, new 4157:4222, down 3.11119
+ import com.github.jonathanxd.dracon.revision.PijulRevisionNumber

11. Edit in "src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt":106 3.10972 "UTF-8"
  up 3.13610, new 4223:4490, down 3.13610
+ 
+     override fun log(project: Project, root: VirtualFile): PijulOperationResult<PijulLog> {
+         val rootPath = Paths.get(VcsUtil.getFilePath(root).path)
+ 
+         val logHashExecution = this.execPijul(project, rootPath, listOf("log", "--hash-only"), delay = 10L)

12. Edit in "src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt":112 3.10972 "UTF-8"
  up 3.13611, new 4491:5952, down 3.13611
+         val hashes = this.doExecutionWithMapper("log--hash-only", logHashExecution) {
+             it.lines()
+         }
+ 
+         if (hashes.statusCode !is SuccessStatusCode) {
+             return hashes as PijulOperationResult<PijulLog>
+         } else {
+             val entries = mutableListOf<PijulLogEntry>()
+             for (hash in hashes.result!!) {
+                 val change = this.doExecutionWithMapper("change-${"$"}hash", this.execPijul(project, rootPath, listOf("change", hash), delay = 10L)) {
+                     it.parseChange(hash)
+                 }
+ 
+                 if (change.statusCode !is SuccessStatusCode) {
+                     return change as PijulOperationResult<PijulLog>
+                 }
+             }
+ 
+             return PijulOperationResult(hashes.operation, hashes.statusCode, PijulLog(entries))
+         }
+     }
+ 
+     override fun latestRevisionNumber(project: Project, root: VirtualFile): PijulOperationResult<PijulRevisionNumber> {
+         /*val root = ProjectLevelVcsManager.getInstance(project).getVcsRootFor(file)
+             ?: return PijulOperationResult("file_status", SuccessStatusCode, FileStatus.UNKNOWN)*/
+         val rootPath = Paths.get(VcsUtil.getFilePath(root).path)
+ 
+         val log = this.log(project, root)
+ 
+         return PijulOperationResult(log.operation, log.statusCode,
+             log.result?.entries?.firstOrNull()?.let {
+                 PijulRevisionNumber(it.changeHash, it.date)
+             }
+         )
+     }
+ 

13. Edit in "src/main/kotlin/com/github/jonathanxd/dracon/PijulVcs.kt":14 3.24146 "UTF-8"
  up 3.24239, new 5953:6018, down 3.24239
+ import com.github.jonathanxd.dracon.provider.PijulChangeProvider

14. Edit in "src/main/kotlin/com/github/jonathanxd/dracon/PijulVcs.kt":20 3.24146 "UTF-8"
  up 3.24475, new 6019:6074, down 3.24475
+ import com.intellij.openapi.vcs.changes.ChangeProvider

15. Edit in "src/main/kotlin/com/github/jonathanxd/dracon/PijulVcs.kt":46 3.24146 "UTF-8"
  up 3.25153, new 6075:6178, down 3.25153
+     override fun getChangeProvider(): ChangeProvider =
+         PijulChangeProvider(this.project, KEY)
+ 

16. File addition: "dada.toml" in "" "UTF-8"
  up 1.0, new 6179:6190

17. Edit in "build.gradle.kts":33 5.13712 "UTF-8"
  up 5.14803, new 6193:6231, down 5.14803
+     maven(url = "https://jitpack.io")

18. Edit in "build.gradle.kts":36 5.13712 "UTF-8"
  up 5.14820, new 6232:6394, down 5.14820
+     implementation("org.tomlj:tomlj:1.0.0")
+     implementation("com.github.JonathanxD.JwIUtils:JwIUtils:4.17.0") {
+         exclude(group = "org.jetbrains")
+     }

19. Replacement in "README.md":21 5.17946 "UTF-8"
B:BD 2.59651 -> 2.59651:59660/2
  up 2.59651, new 6395:8239, down
- - [ ] ...
\
+ - [ ] ...
+ 
+ 
+ # FAQ
+ 
+ ## Why Dracon and not Pijul for IDEA (or something like that)?
+ 
+ Because Dracon is not an official plugin, and I want to make sure that it is clear to anyone who uses this plugin. Dracon is an individual project being developed by [Jonathan H. R. Lopes](https://github.com/JonathanxD) which does not have any relation with Pijul creator. Also, Dracon uses MIT license, allowing to anyone, and that includes the Pijul creator, to contribute and create your own version of Dracon, if wish to.
+ 
+ ## Why Dracon is developed against IntelliJ EAP instead of a stable releases?
+ 
+ Dracon is being developed based in actual [HG4Idea](https://github.com/JetBrains/intellij-community/tree/master/plugins/hg4idea) and [Git4Idea](https://github.com/JetBrains/intellij-community/tree/master/plugins/git4idea) plugins, as well based in current code of [IntelliJ IDEA Community](https://github.com/JetBrains/intellij-community/), and is planned to be released by the end of first semester of 2021, when release time comes, the IntelliJ EAP will be already released as stable, also I don't want to support older releases of IntelliJ IDEA because this involves basing on deprecated code, and this is my first IDEA plugin, so the more I focus the present than the past, more I deliver in terms of better and stable features.
+ 
+ ## Could I contribute to Dracon development?
+ 
+ I'm currently focused on learning how IDEA Plugin platform works and how DVCS is implemented in IDEA, so until Dracon is officially released, I will not be accepting contributions, but Dracon is licensed under MIT, you are free to create your own version of Dracon and developing it on your own.
+ 
+ ## When Dracon will be official released?
+ 
+ I will be periodically releasing Dragon experimental builds, but Dracon stable release is planned by the end of first semester of 2021.
\
        """.trimIndent()

        val change = text.parseChange("DRACON")

        change.changeHash shouldBe "DRACON"
        change.message shouldBe "Initial ChangeProvider"
        change.authors.size shouldBe 1
        change.authors[0].name shouldBe "Author1"
        change.date shouldBe ZonedDateTime.of(2021, 3, 29, 1, 50, 38, 537749028, ZoneOffset.UTC)
        change.dependencies.size shouldBe 5
        change.dependencies[0] shouldBe Dependency(
            IndexInt(2),
            DependencyType.REGULAR_DEPENDENCY,
            "PGNTR2EPCZBOWI67LKY6AN5B3RGIEOQ6NTTXGODLESKDSPWV26KQC"
        )
        change.dependencies[1] shouldBe Dependency(
            IndexInt(3),
            DependencyType.CHANGE_DEPENDENCY,
            "FNNW5IEAXQ43WKB6QSQB7DFLG3Y3T5FYPXIUX7KQ2URR2GU3QLTAC"
        )
        change.dependencies[2] shouldBe Dependency(
            IndexInt(4),
            DependencyType.CHANGE_DEPENDENCY,
            "OPFG6CZ26PPTGTH7ULLRQGZGR3YEIEJOV5W2E3WN7PFRZS62CVLQC"
        )
        change.dependencies[3] shouldBe Dependency(
            IndexInt(5),
            DependencyType.CHANGE_DEPENDENCY,
            "GGYFPXND4VBCROZZXTKAP7Y4JOP2OOYQAFVLMUE7SLFM225EUSIAC"
        )
        change.dependencies[4] shouldBe Dependency(
            Asterisk,
            DependencyType.EXTRA_KNOWN_DEPENDENCY,
            "NTRPUMVQHUIQZ6O72NJ72XFYTZWZOSDA6CSKMUCGKFVNE3KIDYYQC"
        )
        change.hunks.size shouldBe 19
        val sources = change.hunks.map {
            when (it) {
                is FileAddHunk -> it.fileAddHunkAsSource()
                is EditHunk -> it.editHunkAsSource()
                is ReplacementHunk -> it.replacementHunkAsSource()
                else -> it.toString()
            }
        }
        val encoding = Encoding.Charset("UTF-8")

        change.hunks[0] shouldBe FileAddHunk(
            hunkNumber = 1,
            type = HunkType.FILE_ADDITION,
            path = Filename("revision"),
            rootPath = FileDir("src/main/kotlin/com/github/jonathanxd/dracon"),
            lines = emptyList(),
            mode = Mode("+dx"),
            meta = null,
            flags = emptyList(),
            context = Context(up = listOf(3.107), new = Range(0, 10), down = emptyList()),
            encoding = encoding
        )
        change.hunks[1] shouldBe FileAddHunk(
            hunkNumber = 2,
            type = HunkType.FILE_ADDITION,
            path = Filename("PijulRevisionNumber.kt"),
            rootPath = FileDir("src/main/kotlin/com/github/jonathanxd/dracon/revision"),
            lines = listOf(
                LineChange(type = LineChangeType.ADD, data = "package com.github.jonathanxd.dracon.revision\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "import com.intellij.openapi.vcs.changes.patch.BlobIndexUtil\n"
                ),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "import com.intellij.openapi.vcs.history.ShortVcsRevisionNumber\n"
                ),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "import com.intellij.openapi.vcs.history.VcsRevisionNumber\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "import java.time.LocalDateTime\n"),
                LineChange(type = LineChangeType.ADD, data = "import java.time.ZonedDateTime\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "class PijulRevisionNumber(val hash: String, val timestamp: ZonedDateTime) : ShortVcsRevisionNumber {\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "    val NOT_COMMITTED_HASH = BlobIndexUtil.NOT_COMMITTED_HASH\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "    override fun compareTo(other: VcsRevisionNumber): Int {\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "        if (this === other) return 0\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "        if (other is PijulRevisionNumber) {\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "            return this.timestamp.compareTo(other.timestamp)\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "        }\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "        return -1\n"),
                LineChange(type = LineChangeType.ADD, data = "    }\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "    override fun asString(): String = this.hash\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "    override fun toShortString(): String = this.asString()\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "}")
            ),
            mode = null,
            meta = null,
            flags = emptyList(),
            context = Context(up = listOf(0.11), new = Range(12, 36), down = emptyList()),
            encoding = encoding,
        )
        change.hunks[2] shouldBe FileAddHunk(
            hunkNumber = 3,
            type = HunkType.FILE_ADDITION,
            path = Filename("provider"),
            rootPath = FileDir("src/main/kotlin/com/github/jonathanxd/dracon"),
            lines = emptyList(),
            mode = Mode("+dx"),
            meta = null,
            flags = emptyList(),
            context = Context(up = listOf(3.107), new = Range(843, 853), down = emptyList()),
            encoding = encoding,
        )
        change.hunks[3] shouldBe FileAddHunk(
            hunkNumber = 4,
            type = HunkType.FILE_ADDITION,
            path = Filename("PijulChangeProvider.kt"),
            rootPath = FileDir("src/main/kotlin/com/github/jonathanxd/dracon/provider"),
            lines = listOf(
                LineChange(type = LineChangeType.ADD, data = "package com.github.jonathanxd.dracon.provider\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "import com.intellij.openapi.progress.ProgressIndicator\n"),
                LineChange(type = LineChangeType.ADD, data = "import com.intellij.openapi.project.Project\n"),
                LineChange(type = LineChangeType.ADD, data = "import com.intellij.openapi.vcs.VcsKey\n"),
                LineChange(type = LineChangeType.ADD, data = "import com.intellij.openapi.vcs.changes.*\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "class PijulChangeProvider(val project: Project, val key: VcsKey) : ChangeProvider {\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "    override fun getChanges(\n"),
                LineChange(type = LineChangeType.ADD, data = "        dirtyScope: VcsDirtyScope,\n"),
                LineChange(type = LineChangeType.ADD, data = "        builder: ChangelistBuilder,\n"),
                LineChange(type = LineChangeType.ADD, data = "        progress: ProgressIndicator,\n"),
                LineChange(type = LineChangeType.ADD, data = "        addGate: ChangeListManagerGate\n"),
                LineChange(type = LineChangeType.ADD, data = "    ) {\n"),
                LineChange(type = LineChangeType.ADD, data = "        if (project.isDisposed) return\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "        val dirtDirs = dirtyScope.recursivelyDirtyDirectories\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "        println(dirtDirs)\n"),
                LineChange(type = LineChangeType.ADD, data = "    }\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "    override fun isModifiedDocumentTrackingRequired(): Boolean = true\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "}")
            ),
            mode = null,
            meta = null,
            flags = emptyList(),
            context = Context(up = listOf(0.854), new = Range(855, 879), down = emptyList()),
            encoding = encoding,
        )
        change.hunks[4] shouldBe EditHunk(
            hunkNumber = 5,
            type = HunkType.FILE_EDIT,
            path = FilePath("src/main/kotlin/com/github/jonathanxd/dracon/pijul/Pijul.kt"),
            startLine = 13,
            inode = 3.4428,
            lines = listOf(
                LineChange(
                    type = LineChangeType.ADD,
                    data = "import com.github.jonathanxd.dracon.log.PijulLog\n"
                ),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "import com.github.jonathanxd.dracon.revision.PijulRevisionNumber\n"
                )
            ),
            mode = null,
            meta = null,
            flags = emptyList(),
            context = Context(up = listOf(3.4473), new = Range(1584, 1698), down = listOf(3.4473)),
            encoding = encoding,
        )
        change.hunks[5] shouldBe EditHunk(
            hunkNumber = 6,
            type = HunkType.FILE_EDIT,
            path = FilePath("src/main/kotlin/com/github/jonathanxd/dracon/pijul/Pijul.kt"),
            startLine = 82,
            inode = 3.4428,
            lines = listOf(
                LineChange(type = LineChangeType.ADD, data = "    @RequiresBackgroundThread\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "    fun latestRevisionNumber(project: Project, root: VirtualFile): PijulOperationResult<PijulRevisionNumber>\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "    @RequiresBackgroundThread\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "    fun log(project: Project, root: VirtualFile): PijulOperationResult<PijulLog>\n"
                )
            ),
            mode = null,
            meta = null,
            flags = emptyList(),
            context = Context(up = listOf(3.6839), new = Range(1699, 1950), down = listOf(3.6839)),
            encoding = encoding,
        )
        change.hunks[6] shouldBe FileAddHunk(
            hunkNumber = 7,
            type = HunkType.FILE_ADDITION,
            path = Filename("PijulLog.kt"),
            rootPath = FileDir("src/main/kotlin/com/github/jonathanxd/dracon/log"),
            lines = listOf(
                LineChange(type = LineChangeType.ADD, data = "package com.github.jonathanxd.dracon.log\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "import java.time.LocalDateTime\n"),
                LineChange(type = LineChangeType.ADD, data = "import java.time.ZonedDateTime\n"),
                LineChange(type = LineChangeType.ADD, data = "import java.time.format.DateTimeFormatter\n"),
                LineChange(type = LineChangeType.ADD, data = "import java.time.format.ResolverStyle\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "class Author(val name: String?, val fullName: String?, val email: String?)\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "class PijulLog(val entries: List<PijulLogEntry>)\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "class PijulLogEntry(\n"),
                LineChange(type = LineChangeType.ADD, data = "    val changeHash: String,\n"),
                LineChange(type = LineChangeType.ADD, data = "                    val message: String,\n"),
                LineChange(type = LineChangeType.ADD, data = "                    val date: ZonedDateTime,\n"),
                LineChange(type = LineChangeType.ADD, data = "                    val authors: List<Author>\n"),
                LineChange(type = LineChangeType.ADD, data = ")\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "val MESSAGE_PATTERN = Regex(\"message = '(.*)'\\\\n\")\n"),
                LineChange(type = LineChangeType.ADD, data = "val TIME_PATTERN = Regex(\"timestamp = '(.*)'\\\\n\")\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "val AUTHORS_SECTION_PATTERN = Regex(\"\\\\[\\\\[authors\\\\]\\\\]\\n\")\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "val AUTHOR_PATTERN = Regex(\"name = '(.*)'\\\\n\")\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "fun String.parseChange(hash: String): PijulLogEntry {\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "    val message = MESSAGE_PATTERN.find(this)?.groupValues?.get(1)!!\n"
                ),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "    val timestamp = TIME_PATTERN.find(this)?.groupValues?.get(1)!!\n"
                ),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "    val authorsSection = AUTHORS_SECTION_PATTERN.find(this)?.range?.endInclusive\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "    val authors = mutableListOf<Author>()\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "    if (authorsSection != null) {\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "        var lastFound: Int? = authorsSection\n"),
                LineChange(type = LineChangeType.ADD, data = "        while (lastFound != null) {\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "            val foundAuthor = AUTHOR_PATTERN.find(this, lastFound)\n"
                ),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "            val foundAuthorGroup = foundAuthor?.groupValues?.get(1)\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "            if (foundAuthorGroup != null) {\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "                authors += Author(foundAuthorGroup, null, null)\n"
                ),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "                lastFound = if (foundAuthor.range.last + 1 < this.length && this[foundAuthor.range.last + 1] == '\\n') {\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "                    null\n"),
                LineChange(type = LineChangeType.ADD, data = "                } else {\n"),
                LineChange(type = LineChangeType.ADD, data = "                    foundAuthor.range.last\n"),
                LineChange(type = LineChangeType.ADD, data = "                }\n"),
                LineChange(type = LineChangeType.ADD, data = "            } else {\n"),
                LineChange(type = LineChangeType.ADD, data = "                lastFound = null\n"),
                LineChange(type = LineChangeType.ADD, data = "            }\n"),
                LineChange(type = LineChangeType.ADD, data = "        }\n"),
                LineChange(type = LineChangeType.ADD, data = "    }\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "    return PijulLogEntry(hash, message, timestamp.parseAsLocalDateTime(), authors)\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "}\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "val RFC3339_FORMATTER = DateTimeFormatter.ofPattern(\"yyyy-MM-dd'T'HH:mm:ss[.SSSSSSSSS]XXX\")\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "    .withResolverStyle(ResolverStyle.LENIENT)\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "fun String.parseAsLocalDateTime(): ZonedDateTime {\n"),
                LineChange(type = LineChangeType.ADD, data = "    return ZonedDateTime.parse(this, RFC3339_FORMATTER)\n"),
                LineChange(type = LineChangeType.ADD, data = "}")
            ),
            mode = null,
            meta = null,
            flags = emptyList(),
            context = Context(up = listOf(3.6847), new = Range(1951, 1964), down = emptyList()),
            encoding = encoding,
        )
        change.hunks[7] shouldBe EditHunk(
            hunkNumber = 8,
            type = HunkType.FILE_EDIT,
            path = FilePath("src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt"),
            startLine = 13,
            inode = 3.10972,
            lines = listOf(
                LineChange(
                    type = LineChangeType.ADD,
                    data = "import com.github.jonathanxd.dracon.log.PijulLog\n"
                ), LineChange(type = LineChangeType.ADD, data = "import com.github.jonathanxd.dracon.log.PijulLogEntry\n")
            ),
            mode = null,
            meta = null,
            flags = emptyList(),
            context = Context(up = listOf(3.11015), new = Range(4000, 4103), down = listOf(3.11015)),
            encoding = encoding,
        )
        change.hunks[8] shouldBe EditHunk(
            hunkNumber = 9,
            type = HunkType.FILE_EDIT,
            path = FilePath("src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt"),
            startLine = 16,
            inode = 3.10972,
            lines = listOf(
                LineChange(
                    type = LineChangeType.ADD,
                    data = "import com.github.jonathanxd.dracon.log.parseChange\n"
                )
            ),
            mode = null,
            meta = null,
            flags = emptyList(),
            context = Context(up = listOf(3.11075), new = Range(4104, 4156), down = listOf(3.11075)),
            encoding = encoding,
        )
        change.hunks[9] shouldBe EditHunk(
            hunkNumber = 10,
            type = HunkType.FILE_EDIT,
            path = FilePath("src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt"),
            startLine = 20,
            inode = 3.10972,
            lines = listOf(
                LineChange(
                    type = LineChangeType.ADD,
                    data = "import com.github.jonathanxd.dracon.revision.PijulRevisionNumber\n"
                )
            ),
            mode = null,
            meta = null,
            flags = emptyList(),
            context = Context(up = listOf(4.2779), new = Range(4157, 4222), down = listOf(3.11119)),
            encoding = encoding,
        )
        change.hunks[10] shouldBe EditHunk(
            hunkNumber = 11,
            type = HunkType.FILE_EDIT,
            path = FilePath("src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt"),
            startLine = 106,
            inode = 3.10972,
            lines = listOf(
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "    override fun log(project: Project, root: VirtualFile): PijulOperationResult<PijulLog> {\n"
                ),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "        val rootPath = Paths.get(VcsUtil.getFilePath(root).path)\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "        val logHashExecution = this.execPijul(project, rootPath, listOf(\"log\", \"--hash-only\"), delay = 10L)\n"
                )
            ),
            mode = null,
            meta = null,
            flags = emptyList(),
            context = Context(up = listOf(3.1361), new = Range(4223, 4490), down = listOf(3.1361)),
            encoding = encoding,
        )
        change.hunks[11] shouldBe EditHunk(
            hunkNumber = 12,
            type = HunkType.FILE_EDIT,
            path = FilePath("src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt"),
            startLine = 112,
            inode = 3.10972,
            lines = listOf(
                LineChange(
                    type = LineChangeType.ADD,
                    data = "        val hashes = this.doExecutionWithMapper(\"log--hash-only\", logHashExecution) {\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "            it.lines()\n"),
                LineChange(type = LineChangeType.ADD, data = "        }\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "        if (hashes.statusCode !is SuccessStatusCode) {\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "            return hashes as PijulOperationResult<PijulLog>\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "        } else {\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "            val entries = mutableListOf<PijulLogEntry>()\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "            for (hash in hashes.result!!) {\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "                val change = this.doExecutionWithMapper(\"change-\$hash\", this.execPijul(project, rootPath, listOf(\"change\", hash), delay = 10L)) {\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "                    it.parseChange(hash)\n"),
                LineChange(type = LineChangeType.ADD, data = "                }\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "                if (change.statusCode !is SuccessStatusCode) {\n"
                ),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "                    return change as PijulOperationResult<PijulLog>\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "                }\n"),
                LineChange(type = LineChangeType.ADD, data = "            }\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "            return PijulOperationResult(hashes.operation, hashes.statusCode, PijulLog(entries))\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "        }\n"),
                LineChange(type = LineChangeType.ADD, data = "    }\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "    override fun latestRevisionNumber(project: Project, root: VirtualFile): PijulOperationResult<PijulRevisionNumber> {\n"
                ),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "        /*val root = ProjectLevelVcsManager.getInstance(project).getVcsRootFor(file)\n"
                ),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "            ?: return PijulOperationResult(\"file_status\", SuccessStatusCode, FileStatus.UNKNOWN)*/\n"
                ),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "        val rootPath = Paths.get(VcsUtil.getFilePath(root).path)\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "        val log = this.log(project, root)\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "        return PijulOperationResult(log.operation, log.statusCode,\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "            log.result?.entries?.firstOrNull()?.let {\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "                PijulRevisionNumber(it.changeHash, it.date)\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "            }\n"),
                LineChange(type = LineChangeType.ADD, data = "        )\n"),
                LineChange(type = LineChangeType.ADD, data = "    }\n"),
                LineChange(type = LineChangeType.ADD, data = "\n")
            ),
            mode = null,
            meta = null,
            flags = emptyList(),
            context = Context(up = listOf(3.13611), new = Range(4491, 5952), down = listOf(3.13611)),
            encoding = encoding,
        )
        change.hunks[12] shouldBe EditHunk(
            hunkNumber = 13,
            type = HunkType.FILE_EDIT,
            path = FilePath("src/main/kotlin/com/github/jonathanxd/dracon/PijulVcs.kt"),
            startLine = 14,
            inode = 3.24146,
            lines = listOf(
                LineChange(
                    type = LineChangeType.ADD,
                    data = "import com.github.jonathanxd.dracon.provider.PijulChangeProvider\n"
                )
            ),
            mode = null,
            meta = null,
            flags = emptyList(),
            context = Context(up = listOf(3.24239), new = Range(5953, 6018), down = listOf(3.24239)),
            encoding = encoding,
        )
        change.hunks[13] shouldBe EditHunk(
            hunkNumber = 14,
            type = HunkType.FILE_EDIT,
            path = FilePath("src/main/kotlin/com/github/jonathanxd/dracon/PijulVcs.kt"),
            startLine = 20,
            inode = 3.24146,
            lines = listOf(
                LineChange(
                    type = LineChangeType.ADD,
                    data = "import com.intellij.openapi.vcs.changes.ChangeProvider\n"
                )
            ),
            mode = null,
            meta = null,
            flags = emptyList(),
            context = Context(up = listOf(3.24475), new = Range(6019, 6074), down = listOf(3.24475)),
            encoding = encoding,
        )
        change.hunks[14] shouldBe EditHunk(
            hunkNumber = 15,
            type = HunkType.FILE_EDIT,
            path = FilePath("src/main/kotlin/com/github/jonathanxd/dracon/PijulVcs.kt"),
            startLine = 46,
            inode = 3.24146,
            lines = listOf(
                LineChange(
                    type = LineChangeType.ADD,
                    data = "    override fun getChangeProvider(): ChangeProvider =\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "        PijulChangeProvider(this.project, KEY)\n"),
                LineChange(type = LineChangeType.ADD, data = "\n")
            ),
            mode = null,
            meta = null,
            flags = emptyList(),
            context = Context(up = listOf(3.25153), new = Range(6075, 6178), down = listOf(3.25153)),
            encoding = encoding,
        )
        change.hunks[15] shouldBe FileAddHunk(
            hunkNumber = 16,
            type = HunkType.FILE_ADDITION,
            path = Filename("dada.toml"),
            rootPath = FileDir(""),
            lines = emptyList(),
            mode = null,
            meta = null,
            flags = emptyList(),
            context = Context(up = listOf(1.0), new = Range(6179, 6190), down = emptyList()),
            encoding = encoding,
        )
        change.hunks[16] shouldBe EditHunk(
            hunkNumber = 17,
            type = HunkType.FILE_EDIT,
            path = FilePath("build.gradle.kts"),
            startLine = 33,
            inode = 5.13712,
            lines = listOf(LineChange(type = LineChangeType.ADD, data = "    maven(url = \"https://jitpack.io\")\n")),
            mode = null,
            meta = null,
            flags = emptyList(),
            context = Context(up = listOf(5.14803), new = Range(6193, 6231), down = listOf(5.14803)),
            encoding = encoding,
        )
        change.hunks[17] shouldBe EditHunk(
            hunkNumber = 18,
            type = HunkType.FILE_EDIT,
            path = FilePath("build.gradle.kts"),
            startLine = 36,
            inode = 5.13712,
            lines = listOf(
                LineChange(
                    type = LineChangeType.ADD,
                    data = "    implementation(\"org.tomlj:tomlj:1.0.0\")\n"
                ),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "    implementation(\"com.github.JonathanxD.JwIUtils:JwIUtils:4.17.0\") {\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "        exclude(group = \"org.jetbrains\")\n"),
                LineChange(type = LineChangeType.ADD, data = "    }\n")
            ),
            mode = null,
            meta = null,
            flags = emptyList(),
            context = Context(up = listOf(5.1482), new = Range(6232, 6394), down = listOf(5.1482)),
            encoding = encoding,
        )
        change.hunks[18] shouldBe ReplacementHunk(
            hunkNumber = 19,
            type = HunkType.REPLACEMENT,
            path = FilePath("README.md"),
            startLine = 21,
            inode = 5.17946,
            lines = listOf(
                LineChange(type = LineChangeType.DEL, data = "- [ ] ..."),
                LineChange(type = LineChangeType.ADD, data = "- [ ] ...\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "# FAQ\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "## Why Dracon and not Pijul for IDEA (or something like that)?\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "Because Dracon is not an official plugin, and I want to make sure that it is clear to anyone who uses this plugin. Dracon is an individual project being developed by [Jonathan H. R. Lopes](https://github.com/JonathanxD) which does not have any relation with Pijul creator. Also, Dracon uses MIT license, allowing to anyone, and that includes the Pijul creator, to contribute and create your own version of Dracon, if wish to.\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "## Why Dracon is developed against IntelliJ EAP instead of a stable releases?\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "Dracon is being developed based in actual [HG4Idea](https://github.com/JetBrains/intellij-community/tree/master/plugins/hg4idea) and [Git4Idea](https://github.com/JetBrains/intellij-community/tree/master/plugins/git4idea) plugins, as well based in current code of [IntelliJ IDEA Community](https://github.com/JetBrains/intellij-community/), and is planned to be released by the end of first semester of 2021, when release time comes, the IntelliJ EAP will be already released as stable, also I don't want to support older releases of IntelliJ IDEA because this involves basing on deprecated code, and this is my first IDEA plugin, so the more I focus the present than the past, more I deliver in terms of better and stable features.\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "## Could I contribute to Dracon development?\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "I'm currently focused on learning how IDEA Plugin platform works and how DVCS is implemented in IDEA, so until Dracon is officially released, I will not be accepting contributions, but Dracon is licensed under MIT, you are free to create your own version of Dracon and developing it on your own.\n"
                ),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(type = LineChangeType.ADD, data = "## When Dracon will be official released?\n"),
                LineChange(type = LineChangeType.ADD, data = "\n"),
                LineChange(
                    type = LineChangeType.ADD,
                    data = "I will be periodically releasing Dragon experimental builds, but Dracon stable release is planned by the end of first semester of 2021."
                )
            ),
            mode = null,
            meta = null,
            flags = emptyList(),
            context = Context(up = listOf(2.59651), new = Range(6395, 8239), down = emptyList()),
            encoding = encoding,
        )
    }
})