Experimental

[?]
May 17, 2021, 7:35 AM
VBL5BQH7K5QZH3KCO4JBRDVYAN4YXYNAWETL2WVUD2PYHNZAGMTAC

Dependencies

  • [2] DLDMHQY6 Add experimental build 3 and options
  • [3] RE4EKNSL Improvements, a lot
  • [4] OMZXJL6Q Ready for pijul push! First nightly build will be released shortly!
  • [5] A7IL6I3V More files to support .ignore
  • [6] 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.
  • [7] QXUEMZ3B Initial CahngeProvider
  • [8] ZCRW57C5 Improved support for revisions
  • [9] 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).
  • [10] Q7FXTHVU First record support, YEAAAH, RECOOORD
  • [11] 5AUENX2Y Add support to view files affected by a revision
  • [12] 7L5LODGZ Parse changes from `pijul change`
  • [13] MTPTFTHG Initial plugin 2
  • [14] FRFFQV7V Basic show history support.
  • [15] B43WNBLF - Add Show History to Pijul menu - Always ignore .idea and .pijul in tracking. - Make findPijul a generic function to allow to find editor-server. - Only show one revision for directories. - Add `Hunk::resolvePath(Path)` to resolve the affected file to a Java NIO Path. - Fix StringOutOfBounds in Change Parsering Algorithm - Use editor-server instead of copie for interfacing with `pijul record` file. - Fix FileStatus provider not returning correctly for untracked files. - Add CommittedChangesProvider for Pijul.
  • [16] GGYFPXND Initial plugin
  • [17] 37OJKSWJ Improved caching code a lot
  • [18] OPFG6CZ2 File status tracking supported.
  • [19] POQV6EZE Options screen
  • [*] FNNW5IEA Added more plugin files to Pijul
  • [*] 6CR2EFUN First ChangeProvider implementation!!! Wheehooo
  • [*] MZYZIVHY First experimental build, it seems like it is breaking Git plugin, however, it still something =D

Change contents

  • replacement in src/main/resources/messages/DraconBundle.properties at line 118
    [2.437][2.437:523]()
    caching uses a bunch of storage space and takes a bit of more time at first loading.
    [2.437]
    caching uses a bunch of storage space and takes a bit of more time at first loading.
    pijul.log.refGroup.default=Default
    pijul.log.refGroup.current=Current
    pijul.log.refGroup.channel=Channel
    pijul.log.refGroup.tag=Tag
    pijul.log.refGroup.tag_text={0}
    pijul.log.refGroup.mainChannel=main
    pijul.log.refGroup.other=Other
  • edit in src/main/resources/META-INF/plugin.xml at line 42
    [3.2303]
    [3.9628]
    <logProvider implementation="com.github.jonathanxd.dracon.log.PijulLogProvider"/>
  • file addition: VirtualFile.kt (----------)
    [21.1784]
    package com.github.jonathanxd.dracon.util
    import com.intellij.openapi.vcs.FilePath
    import com.intellij.openapi.vfs.VirtualFile
    import com.intellij.vcsUtil.VcsUtil
    import java.nio.file.Path
    import java.nio.file.Paths
    fun VirtualFile.convertToNio(): Path =
    Paths.get(VcsUtil.getFilePath(this).path)
    fun FilePath.convertToNio(): Path =
    Paths.get(this.path)
  • file addition: Project.kt (----------)
    [21.1784]
    package com.github.jonathanxd.dracon.util
    import com.intellij.openapi.project.Project
    fun Project.pijul() =
    com.github.jonathanxd.dracon.pijul.pijul(this)
    fun Project.pijulVcs() =
    com.github.jonathanxd.dracon.pijulVcs(this)
  • file addition: BiDiMap.kt (----------)
    [21.1784]
    package com.github.jonathanxd.dracon.util
    import com.github.jonathanxd.iutils.collection.view.ViewCollections
    import com.github.jonathanxd.iutils.collection.wrapper.WrapperCollections
    import com.intellij.util.containers.map2Array
    interface BiDiMap<K, V> : Map<K, V> {
    val otherDirection: BiDiMap<V, K>
    }
    interface MutableBiDiMap<K, V> : BiDiMap<K, V>, MutableMap<K, V> {
    override val otherDirection: MutableBiDiMap<V, K>
    }
    class BiDiMapImpl<K, V>(val kvMap: Map<K, V>,
    val vkMap: Map<V, K>): BiDiMap<K, V> {
    constructor(map: Map<K, V>): this(map, map.createVKMap())
    override val entries: Set<Map.Entry<K, V>>
    get() = this.kvMap.entries
    override val keys: Set<K>
    get() = this.kvMap.keys
    override val size: Int
    get() = this.kvMap.size
    override val values: Collection<V>
    get() = this.kvMap.values
    override fun containsKey(key: K): Boolean = this.kvMap.containsKey(key)
    override fun containsValue(value: V): Boolean = this.kvMap.containsValue(value)
    override fun get(key: K): V? = this.kvMap[key]
    override fun isEmpty(): Boolean = this.kvMap.isEmpty()
    override val otherDirection: BiDiMap<V, K> = OtherDirection()
    inner class OtherDirection: BiDiMap<V, K> {
    override val entries: Set<Map.Entry<V, K>>
    get() = this@BiDiMapImpl.vkMap.entries
    override val keys: Set<V>
    get() = this@BiDiMapImpl.vkMap.keys
    override val size: Int
    get() = this@BiDiMapImpl.vkMap.size
    override val values: Collection<K>
    get() = this@BiDiMapImpl.vkMap.values
    override fun containsKey(key: V): Boolean = this@BiDiMapImpl.vkMap.containsKey(key)
    override fun containsValue(value: K): Boolean = this@BiDiMapImpl.vkMap.containsValue(value)
    override fun get(key: V): K? = this@BiDiMapImpl.vkMap[key]
    override fun isEmpty(): Boolean = this@BiDiMapImpl.vkMap.isEmpty()
    override val otherDirection: BiDiMap<K, V>
    get() = this@BiDiMapImpl
    }
    }
    class MutableBiDiMapImpl<K, V>(val kvMap: MutableMap<K, V>,
    val vkMap: MutableMap<V, K>): MutableBiDiMap<K, V> {
    constructor(map: MutableMap<K, V>): this(map, map.createVKMutableMap())
    override val entries: MutableSet<MutableMap.MutableEntry<K, V>>
    get() = ViewCollections.setMapped(
    this.kvMap.entries,
    { MutableBiDiEntry(it, this.vkMap)},
    {
    this.kvMap[it.key] = it.value
    this.vkMap[it.value] = it.key
    true
    },
    {
    this.kvMap.remove(it.key, it.value)
    this.vkMap.remove(it.value, it.key)
    true
    }
    )
    override val keys: MutableSet<K>
    get() = ViewCollections.setMapped(this.kvMap.keys,
    {it},
    {
    false
    },
    {
    val value = this.kvMap.remove(it)
    this.vkMap.remove(value)
    true
    }
    )
    override val values: MutableCollection<V>
    get() = ViewCollections.collectionMapped(this.kvMap.values,
    {it},
    {
    false
    },
    {
    val key = this.vkMap.remove(it)
    this.kvMap.remove(key)
    true
    }
    )
    override val size: Int
    get() = this.kvMap.size
    override fun containsKey(key: K): Boolean = this.kvMap.containsKey(key)
    override fun containsValue(value: V): Boolean = this.kvMap.containsValue(value)
    override fun get(key: K): V? = this.kvMap[key]
    override fun isEmpty(): Boolean = this.kvMap.isEmpty()
    override fun clear() {
    this.kvMap.clear()
    this.vkMap.clear()
    }
    override fun remove(key: K): V? {
    val value = this.kvMap.remove(key)
    this.vkMap.remove(value)
    return value
    }
    override fun put(key: K, value: V): V? {
    val oldValue = this.kvMap.put(key, value)
    this.vkMap[value] = key
    return oldValue
    }
    override fun putAll(from: Map<out K, V>) {
    for ((k, v) in from) {
    this[k] = v
    }
    }
    override val otherDirection: MutableBiDiMap<V, K> = OtherDirection()
    inner class OtherDirection: MutableBiDiMap<V, K> {
    override val entries: MutableSet<MutableMap.MutableEntry<V, K>>
    get() = ViewCollections.setMapped(
    this@MutableBiDiMapImpl.vkMap.entries,
    { MutableBiDiEntry(it, this@MutableBiDiMapImpl.kvMap)},
    {
    this@MutableBiDiMapImpl.vkMap[it.key] = it.value
    this@MutableBiDiMapImpl.kvMap[it.value] = it.key
    true
    },
    {
    this@MutableBiDiMapImpl.vkMap.remove(it.key, it.value)
    this@MutableBiDiMapImpl.kvMap.remove(it.value, it.key)
    true
    }
    )
    override val keys: MutableSet<V>
    get() = ViewCollections.setMapped(this@MutableBiDiMapImpl.vkMap.keys,
    {it},
    {
    false
    },
    {
    val value = this@MutableBiDiMapImpl.vkMap.remove(it)
    this@MutableBiDiMapImpl.kvMap.remove(value)
    true
    }
    )
    override val values: MutableCollection<K>
    get() = ViewCollections.collectionMapped(this@MutableBiDiMapImpl.vkMap.values,
    {it},
    {
    false
    },
    {
    val key = this@MutableBiDiMapImpl.kvMap.remove(it)
    this@MutableBiDiMapImpl.vkMap.remove(key)
    true
    }
    )
    override val size: Int
    get() = this@MutableBiDiMapImpl.vkMap.size
    override fun containsKey(key: V): Boolean = this@MutableBiDiMapImpl.vkMap.containsKey(key)
    override fun containsValue(value: K): Boolean = this@MutableBiDiMapImpl.vkMap.containsValue(value)
    override fun get(key: V): K? = this@MutableBiDiMapImpl.vkMap[key]
    override fun isEmpty(): Boolean = this@MutableBiDiMapImpl.vkMap.isEmpty()
    override val otherDirection: MutableBiDiMap<K, V>
    get() = this@MutableBiDiMapImpl
    override fun clear() {
    this@MutableBiDiMapImpl.kvMap.clear()
    this@MutableBiDiMapImpl.vkMap.clear()
    }
    override fun remove(key: V): K? {
    val value = this@MutableBiDiMapImpl.vkMap.remove(key)
    this@MutableBiDiMapImpl.kvMap.remove(value)
    return value
    }
    override fun put(key: V, value: K): K? {
    val oldValue = this@MutableBiDiMapImpl.vkMap.put(key, value)
    this@MutableBiDiMapImpl.kvMap[value] = key
    return oldValue
    }
    override fun putAll(from: Map<out V, K>) {
    for ((k, v) in from) {
    this[k] = v
    }
    }
    }
    }
    class MutableBiDiEntry<K, V>(val entry: MutableMap.MutableEntry<K, V>, val vkMap: MutableMap<V, K>) : MutableMap.MutableEntry<K, V> {
    override val key: K
    get() = entry.key
    override val value: V
    get() = entry.value
    override fun setValue(newValue: V): V {
    this.vkMap[newValue] = this.key
    return entry.setValue(newValue)
    }
    }
    fun <K, V> Map<K, V>.createVKMap(): Map<V, K> {
    val map = mutableMapOf<V, K>()
    this.entries.forEach {
    map[it.value] = it.key
    }
    return map
    }
    fun <K, V> MutableMap<K, V>.createVKMutableMap(): MutableMap<V, K> {
    val map = mutableMapOf<V, K>()
    this.entries.forEach {
    map[it.value] = it.key
    }
    return map
    }
    fun <K, V> mutableBiDiMap(vararg pairs: Pair<K, V>): MutableBiDiMap<K, V> =
    MutableBiDiMapImpl(
    mutableMapOf(*pairs),
    mutableMapOf(*pairs.inverted()),
    )
    fun <K, V> biDiMap(vararg pairs: Pair<K, V>): BiDiMap<K, V> =
    BiDiMapImpl(
    mutableMapOf(*pairs),
    mutableMapOf(*pairs.inverted()),
    )
    fun <K, V> Array<out Pair<K, V>>.inverted(): Array<Pair<V, K>> =
    Array(this.size) {
    this[it].second to this[it].first
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/revision/RevisionContentResolver.kt at line 4
    [3.11298]
    [3.2549]
    import com.github.jonathanxd.dracon.ignore.IgnoreUtil
    import com.github.jonathanxd.dracon.pijul.Pijul
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/revision/RevisionContentResolver.kt at line 39
    [3.1627][3.1627:1732]()
    copyFolder(root, tmpTarget, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING)
    [3.1627]
    [3.1732]
    copyFolder(root, root, tmpTarget, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING)
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/revision/RevisionContentResolver.kt at line 66
    [3.790][3.790:895]()
    copyFolder(root, tmpTarget, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING)
    [3.440]
    [3.895]
    copyFolder(root, root, tmpTarget, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING)
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/revision/RevisionContentResolver.kt at line 127
    [3.1256][3.12200:12305](),[3.12200][3.12200:12305]()
    copyFolder(root, tmpTarget, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING)
    [3.1256]
    [3.12305]
    copyFolder(root, root, tmpTarget, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING)
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/revision/RevisionContentResolver.kt at line 199
    [3.2105][3.2105:2210]()
    copyFolder(root, tmpTarget, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING)
    [3.2105]
    [3.2210]
    copyFolder(root, root, tmpTarget, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING)
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/revision/RevisionContentResolver.kt at line 246
    [3.14662][3.14662:14767]()
    copyFolder(root, tmpTarget, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING)
    [3.14662]
    [3.14767]
    copyFolder(root, root, tmpTarget, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING)
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/revision/RevisionContentResolver.kt at line 460
    [3.8042][3.8042:8117]()
    copyFolder(lastFoundCachedRevisionPath, temporaryWorkingDirectory)
    [3.8042]
    [3.8117]
    copyFolder(root, lastFoundCachedRevisionPath, temporaryWorkingDirectory)
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/revision/RevisionContentResolver.kt at line 463
    [3.8204][3.8204:8256]()
    copyFolder(root, temporaryWorkingDirectory)
    [3.8204]
    [3.8256]
    copyFolder(root, root, temporaryWorkingDirectory)
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/revision/RevisionContentResolver.kt at line 507
    [3.10348][3.10348:10423]()
    copyFolder(resolvedPathForRevision, temporaryWorkingDirectory)
    [3.10348]
    [3.10423]
    copyFolder(root, resolvedPathForRevision, temporaryWorkingDirectory)
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/revision/RevisionContentResolver.kt at line 524
    [3.11212][3.11212:11287]()
    copyFolder(temporaryWorkingDirectory, resolvedPathForRevision)
    [3.11212]
    [3.11287]
    copyFolder(root, temporaryWorkingDirectory, resolvedPathForRevision)
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/revision/RevisionContentResolver.kt at line 540
    [3.2279][3.2279:2352]()
    fun copyFolder(source: Path, target: Path, vararg options: CopyOption) {
    [3.2279]
    [3.11552]
    fun copyFolder(pijulRoot: Path,
    source: Path,
    target: Path,
    vararg options: CopyOption) {
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/revision/RevisionContentResolver.kt at line 551
    [3.2681]
    [3.2681]
    if (IgnoreUtil.isIgnored(pijulRoot, dir))
    return FileVisitResult.SKIP_SUBTREE
  • file addition: ChannelRevision.kt (----------)
    [3.11]
    package com.github.jonathanxd.dracon.revision
    data class ChannelRevision(val channel: String, val revision: PijulRevisionNumber)
    data class ChannelRevisions(val revisionsByChannel: List<ChannelRevision>)
  • file addition: PijulVcsLogRefManager.kt (----------)
    [3.1127]
    package com.github.jonathanxd.dracon.repository
    import com.github.jonathanxd.dracon.channel.PijulChannelManager
    import com.github.jonathanxd.dracon.channel.PijulChannelType
    import com.github.jonathanxd.dracon.i18n.DraconBundle
    import com.github.jonathanxd.dracon.util.BiDiMap
    import com.github.jonathanxd.dracon.util.biDiMap
    import com.intellij.openapi.components.service
    import com.intellij.openapi.project.Project
    import com.intellij.vcs.log.*
    import com.intellij.vcs.log.impl.SimpleRefGroup
    import com.intellij.vcs.log.impl.SimpleRefType
    import java.io.DataInput
    import java.io.DataOutput
    class PijulVcsLogRefManager(val project: Project) : VcsLogRefManager {
    companion object {
    val CURRENT: VcsRefType = SimpleRefType("CURRENT", false, VcsLogStandardColors.Refs.TIP)
    val CHANNEL: VcsRefType = SimpleRefType("CHANNEL", true, VcsLogStandardColors.Refs.BRANCH)
    val TAG: VcsRefType = SimpleRefType("TAG", false, VcsLogStandardColors.Refs.TAG)
    val OTHER: VcsRefType = SimpleRefType("OTHER", true, VcsLogStandardColors.Refs.TAG)
    private val REF_TYPE_INDEX: BiDiMap<VcsRefType, Int> = biDiMap(
    CURRENT to 0,
    CHANNEL to 1,
    TAG to 2,
    OTHER to 100
    )
    }
    private val labelSorter = Comparator<VcsRef> { l, r ->
    REF_TYPE_INDEX[l.type]!!.compareTo(REF_TYPE_INDEX[r.type]!!)
    }
    private val channelSorter = Comparator<VcsRef> { l, r ->
    REF_TYPE_INDEX[l.type]!!.compareTo(REF_TYPE_INDEX[r.type]!!)
    }
    val channelManager = project.service<PijulChannelManager>()
    val repositoryManager = project.service<PijulRepositoryManager>()
    override fun getBranchLayoutComparator(): Comparator<VcsRef> = this.channelSorter
    override fun getLabelsOrderComparator(): Comparator<VcsRef> = this.labelSorter
    override fun groupForBranchFilter(refs: MutableCollection<out VcsRef>): MutableList<RefGroup> {
    val current = mutableListOf<VcsRef>()
    val channels = mutableListOf<VcsRef>()
    val tags = mutableListOf<VcsRef>()
    val others = mutableListOf<VcsRef>()
    for (ref in refs) {
    when (ref.type) {
    CURRENT -> {
    current.add(ref)
    }
    CHANNEL -> {
    channels.add(ref)
    }
    TAG -> {
    tags.add(ref)
    }
    else -> {
    others.add(ref)
    }
    }
    }
    val groups = mutableListOf<RefGroup>()
    if (current.isNotEmpty()) {
    groups.add(SimpleRefGroup(DraconBundle.message("pijul.log.refGroup.current"), current.toList()))
    }
    if (channels.isNotEmpty()) {
    groups.add(SimpleRefGroup(DraconBundle.message("pijul.log.refGroup.channel"), channels.toList()))
    }
    if (tags.isNotEmpty()) {
    groups.add(SimpleRefGroup(DraconBundle.message("pijul.log.refGroup.tag"), tags.toList()))
    }
    if (others.isNotEmpty()) {
    groups.add(SimpleRefGroup(DraconBundle.message("pijul.log.refGroup.other"), others.toList()))
    }
    return groups
    }
    override fun groupForTable(
    refs: MutableCollection<out VcsRef>,
    compact: Boolean,
    showTagNames: Boolean
    ): MutableList<RefGroup> {
    // TODO: Support compact and showTagNames
    val mainChannels = mutableListOf<VcsRef>()
    val channels = mutableListOf<VcsRef>()
    val tags = mutableListOf<VcsRef>()
    val others = mutableListOf<VcsRef>()
    for (ref in refs) {
    when (ref.type) {
    CURRENT -> {}
    CHANNEL -> {
    if (ref.name == "main") {
    mainChannels.add(ref)
    } else {
    channels.add(ref)
    }
    }
    TAG -> {
    tags.add(ref)
    }
    else -> {
    others.add(ref)
    }
    }
    }
    val hasCurrent = refs.any { it.type == CURRENT }
    val groups = mutableListOf<RefGroup>()
    if (mainChannels.isNotEmpty() && hasCurrent) {
    groups.add(SimpleRefGroup(DraconBundle.message("pijul.log.refGroup.mainChannel"), mainChannels.toList()))
    }
    if (channels.isNotEmpty()) {
    groups.add(SimpleRefGroup(DraconBundle.message("pijul.log.refGroup.channel"), channels.toList()))
    }
    if (tags.isNotEmpty()) {
    val f = tags.first()
    groups.add(SimpleRefGroup(DraconBundle.message("pijul.log.refGroup.tag_text", f.name), tags.toList()))
    }
    if (others.isNotEmpty()) {
    groups.add(SimpleRefGroup(DraconBundle.message("pijul.log.refGroup.other"), others.toList()))
    }
    return groups
    }
    override fun serialize(out: DataOutput, type: VcsRefType) {
    out.writeInt(REF_TYPE_INDEX[type]!!)
    }
    override fun deserialize(input: DataInput): VcsRefType {
    val id = input.readInt()
    return REF_TYPE_INDEX.otherDirection[id]!!
    }
    override fun isFavorite(reference: VcsRef): Boolean =
    when (reference.type) {
    CURRENT -> true
    CHANNEL -> this.channelManager.isFavorite(
    PijulChannelType.CHANNEL,
    this.repositoryManager.getRepositoryForFileQuick(reference.root),
    reference.name
    )
    else -> false
    }
    override fun setFavorite(reference: VcsRef, favorite: Boolean) {
    when (reference.type) {
    CURRENT -> return
    CHANNEL -> this.channelManager.setFavorite(
    PijulChannelType.CHANNEL,
    this.repositoryManager.getRepositoryForFileQuick(reference.root),
    reference.name,
    favorite
    )
    else -> return
    }
    }
    }
  • file addition: PijulRepositoryChangeListener.kt (----------)
    [3.1127]
    package com.github.jonathanxd.dracon.repository
    @FunctionalInterface
    interface PijulRepositoryChangeListener {
    fun repositoryChanged(repository: PijulRepository)
    }
    fun PijulRepositoryChangeListener(f: (repository: PijulRepository) -> Unit): PijulRepositoryChangeListener =
    object : PijulRepositoryChangeListener {
    override fun repositoryChanged(repository: PijulRepository) {
    f(repository)
    }
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/repository/PijulRepository.kt at line 3
    [3.3804][3.3804:3849]()
    import com.github.jonathanxd.dracon.PijulVcs
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/repository/PijulRepository.kt at line 21
    [3.4639]
    [3.4639]
    import com.intellij.util.messages.Topic
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/repository/PijulRepository.kt at line 49
    [3.5336]
    [3.5336]
    val PIJUL_REPO_CHANGE: Topic<PijulRepositoryChangeListener> = Topic.create(
    "PijulRepository change",
    PijulRepositoryChangeListener::class.java
    )
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/push/PijulVcsFullCommitDetails.kt at line 28
    [3.11881][3.11881:11953]()
    override fun getTimestamp(): Long = this.entry.date.toEpochSecond()
    [3.11881]
    [3.11953]
    override fun getTimestamp(): Long = this.entry.date.toInstant().toEpochMilli()
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/push/PijulVcsFullCommitDetails.kt at line 34
    [3.12109][3.12109:12204]()
    if (this.entry.message.isNotEmpty()) ""
    else this.entry.message.split("\n")[0]
    [3.12109]
    [3.12204]
    if (this.entry.message.isEmpty()) ""
    else this.entry.message.split("\n").first { it.trim().isNotEmpty() }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/provider/PijulChangeProvider.kt at line 64
    [3.4305]
    [22.1338]
    val knownPaths = mutableSetOf<Path>()
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/provider/PijulChangeProvider.kt at line 69
    [3.3738]
    [22.1515]
    if (knownPaths.contains(path)) continue
    knownPaths.add(path)
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/provider/PijulChangeProvider.kt at line 82
    [3.3801]
    [22.2214]
    if (knownPaths.contains(path)) continue
    knownPaths.add(path)
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/provider/PijulChangeProvider.kt at line 101
    [22.3003]
    [22.3003]
    if (knownPaths.contains(path)) continue
    knownPaths.add(path)
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/provider/PijulChangeProvider.kt at line 118
    [22.3702]
    [22.3702]
    if (knownPaths.contains(path)) continue
    knownPaths.add(path)
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/pijul/PijulOperationResult.kt at line 28
    [3.12980]
    [3.6894]
    fun <Y> flatMap(f: (R) -> PijulOperationResult<Y>): PijulOperationResult<Y> =
    if (this.result != null) {
    f(this.result)
    } else {
    this as PijulOperationResult<Y>
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/pijul/Pijul.kt at line 18
    [22.4514]
    [3.22572]
    import com.github.jonathanxd.dracon.log.PijulTag
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/pijul/Pijul.kt at line 20
    [3.22633]
    [3.1633]
    import com.github.jonathanxd.dracon.revision.ChannelRevisions
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/pijul/Pijul.kt at line 67
    [3.2400]
    [3.2400]
    }
    dir = dir.parent
    }
    return null
    }
    fun findPijulDirectoryPath(root: Path): Path? {
    var dir: Path? = root
    while (dir != null) {
    if (isPijulRepository(dir)) {
    return dir
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/pijul/Pijul.kt at line 117
    [3.13172]
    [3.4539]
    @RequiresBackgroundThread
    fun revisionByChannel(project: Project, root: Path): PijulOperationResult<ChannelRevisions>
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/pijul/Pijul.kt at line 188
    [3.13423]
    [3.13423]
    fun log(project: Project, root: Path, channel: String): PijulOperationResult<PijulLog>
    /**
    * Retrieves change history
    */
    @RequiresBackgroundThread
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/pijul/Pijul.kt at line 200
    [3.13576]
    [3.13576]
    fun tags(project: Project, root: Path): PijulOperationResult<List<PijulTag>>
    /**
    * Retrieves change history
    */
    @RequiresBackgroundThread
  • file addition: PijulTag.kt (----------)
    [21.6847]
    package com.github.jonathanxd.dracon.log
    import com.github.jonathanxd.dracon.push.parseDate
    import org.tomlj.Toml
    import java.time.ZonedDateTime
    import java.util.*
    data class PijulTag(
    val hash: String,
    val authors: List<Author>,
    val date: ZonedDateTime,
    val state: String,
    val message: String
    )
    val PijulTag.simpleMessage get() =
    if (this.message.isEmpty()) ""
    else this.message.split("\n").first { it.trim().isNotEmpty() }.trim()
    val AUTHOR_REGEX = Regex("Author \\{ name: (\"([^\"]+)\"|None), full_name: (Some\\(\"([^\"]+)\"\\)|None), email: (Some\\(\"([^\"]+)\"\\)|None) }")
    fun String.parseTags(): List<PijulTag> {
    if (this.isEmpty()) return emptyList()
    val lines = this.lines().listIterator()
    val tags = mutableListOf<PijulTag>()
    while (lines.hasNext()) {
    var hash: String? = null
    val authors = mutableListOf<Author>()
    var date: ZonedDateTime? = null
    var state: String? = null
    val message = StringJoiner("\n")
    var messageStarted = false
    while (lines.hasNext()) {
    val line = lines.next()
    if (line.startsWith("Tag")) {
    hash = line.substring("Tag ".length)
    } else if (line.startsWith("Author: ")) {
    val finds = AUTHOR_REGEX.findAll(line)
    for (find in finds) {
    val groups = find.groups
    val name: String? = groups[2]?.value
    val fullName: String? = groups[4]?.value
    val email: String? = groups[6]?.value
    authors += Author(name, fullName, email)
    }
    } else if (line.startsWith("Date: ")) {
    val dateString = line.substring("Date: ".length)
    date = dateString.parseDate()
    } else if (line.startsWith("State: ")) {
    state = line.substring("State: ".length)
    } else {
    if (line.startsWith("Tag")) {
    lines.previous()
    break;
    } else if (line.trim().isEmpty() && state != null && !messageStarted) {
    messageStarted = true
    } else {
    if (line.startsWith(" ")) {
    message.add(line.substring(" ".length))
    } else {
    message.add(line)
    }
    }
    }
    }
    tags += PijulTag(hash!!, authors, date!!, state!!, message.toString().removeTrailingLineJump())
    }
    return tags
    }
    private val TRAILING_LINE_JUMP = Regex("[\n]+$")
    fun String.removeTrailingLineJump() =
    this.replace(TRAILING_LINE_JUMP, "")
  • file addition: PijulRecordDetails.kt (----------)
    [21.6847]
    package com.github.jonathanxd.dracon.log
    import com.intellij.openapi.project.Project
    import com.intellij.openapi.vcs.changes.Change
    import com.intellij.openapi.vfs.VirtualFile
    import com.intellij.vcs.log.VcsShortCommitDetails
    import com.intellij.vcs.log.impl.VcsChangesLazilyParsedDetails
    import com.intellij.vcs.log.impl.VcsChangesLazilyParsedDetails.ChangesParser
    import com.intellij.vcs.log.impl.VcsFileStatusInfo
    import java.util.*
    class PijulRecordDetails(val project: Project,
    val rootFile: VirtualFile,
    val entry: PijulLogEntryCommitDetails) : VcsChangesLazilyParsedDetails(
    project, entry.id, emptyList(), entry.commitTime, rootFile, entry.subject, entry.author,
    entry.fullMessage, entry.committer, entry.authorTime,
    (listOf(PijulHash(entry.entry.changeHash)) /*+ entry.getPijulParents()*/).map {
    entry.changeRetriever(it.hash).map {
    VcsFileStatusInfo(
    it.type,
    (it.beforeRevision?.file?.path ?: it.afterRevision?.file?.path)!!,
    it.afterRevision?.file?.path
    )
    }
    },
    PijulChangesParser(entry)
    )
    private class PijulChangesParser(val entry: PijulLogEntryCommitDetails) : ChangesParser {
    override fun parseStatusInfo(
    project: Project,
    commit: VcsShortCommitDetails,
    changes: List<VcsFileStatusInfo>,
    parentIndex: Int
    ): List<Change> {
    var parentHash: String? = null
    /*if (parentIndex < commit.parents.size) {
    parentHash = commit.parents[parentIndex].asString()
    }*/
    return entry.changeRetriever(parentHash ?: entry.entry.changeHash)
    }
    }
  • file addition: PijulLogProvider.kt (----------)
    [21.6847]
    package com.github.jonathanxd.dracon.log
    import com.github.jonathanxd.dracon.PijulVcs
    import com.github.jonathanxd.dracon.changes.PijulCommittedChangeList
    import com.github.jonathanxd.dracon.pijul.Pijul
    import com.github.jonathanxd.dracon.pijul.pijul
    import com.github.jonathanxd.dracon.repository.PijulRepository
    import com.github.jonathanxd.dracon.repository.PijulRepositoryChangeListener
    import com.github.jonathanxd.dracon.repository.PijulVcsLogRefManager
    import com.github.jonathanxd.dracon.util.convertToNio
    import com.github.jonathanxd.dracon.util.pijul
    import com.intellij.openapi.Disposable
    import com.intellij.openapi.application.ReadAction
    import com.intellij.openapi.project.Project
    import com.intellij.openapi.vcs.FilePath
    import com.intellij.openapi.vcs.VcsKey
    import com.intellij.openapi.vfs.VirtualFile
    import com.intellij.util.Consumer
    import com.intellij.util.messages.MessageBusConnection
    import com.intellij.vcs.log.*
    import com.intellij.vcs.log.impl.HashImpl
    import com.intellij.vcs.log.impl.LogDataImpl
    import com.intellij.vcs.log.impl.VcsUserImpl
    import org.apache.commons.codec.digest.DigestUtils
    import java.time.ZoneId
    class PijulLogProvider(val project: Project) : VcsLogProvider {
    val manager = PijulVcsLogRefManager(project)
    override fun readFirstBlock(
    root: VirtualFile,
    requirements: VcsLogProvider.Requirements
    ): VcsLogProvider.DetailedLogData {
    return createMetadata(this.project, root) {
    this.project.pijul().log(this.project, root.convertToNio(), it).result?.entries.orEmpty()
    }
    }
    override fun readAllHashes(root: VirtualFile, commitConsumer: Consumer<in TimedVcsCommit>): VcsLogProvider.LogData {
    return createMetadata(this.project, root, {
    this.project.pijul().log(this.project, root.convertToNio(), it).result?.entries.orEmpty()
    }, { commitConsumer.consume(it) })
    }
    override fun readMetadata(
    root: VirtualFile,
    hashes: MutableList<String>,
    consumer: Consumer<in VcsCommitMetadata>
    ) {
    createMetadata(this.project, root, {
    this.project.pijul().log(this.project, root.convertToNio(), it).result?.entries.orEmpty().filter {
    hashes.contains(DigestUtils.sha1Hex(it.changeHash))
    }
    }, {
    consumer.consume(it)
    })
    }
    override fun readFullDetails(
    root: VirtualFile,
    hashes: MutableList<String>,
    commitConsumer: Consumer<in VcsFullCommitDetails>
    ) {
    createMetadataForEntries(this.project, root, {
    this.project.pijul().log(this.project, root.convertToNio(), it).result?.entries.orEmpty().filter {
    hashes.contains(DigestUtils.sha1Hex(it.changeHash))
    }
    }, { _, it ->
    commitConsumer.consume(PijulRecordDetails(this.project, root, it))
    })
    }
    override fun getSupportedVcs(): VcsKey {
    return PijulVcs.KEY
    }
    override fun getReferenceManager(): VcsLogRefManager =
    this.manager
    override fun subscribeToRootRefreshEvents(
    roots: MutableCollection<out VirtualFile>,
    refresher: VcsLogRefresher
    ): Disposable {
    val connection: MessageBusConnection = this.project.messageBus.connect()
    connection.subscribe(PijulRepository.PIJUL_REPO_CHANGE, PijulRepositoryChangeListener { repository ->
    val root: VirtualFile = repository.root
    if (roots.contains(root)) {
    refresher.refresh(root)
    }
    })
    return connection
    }
    override fun getCommitsMatchingFilter(
    root: VirtualFile,
    filterCollection: VcsLogFilterCollection,
    maxCount: Int
    ): MutableList<TimedVcsCommit> {
    val rootPath = root.convertToNio()
    val channelFilters = mutableListOf<(String) -> Boolean>()
    val filters = mutableListOf<(PijulLogEntry) -> Boolean>()
    val fullDetailsFilters = mutableListOf<(VcsFullCommitDetails) -> Boolean>()
    val metadataFilters = mutableListOf<(VcsCommitMetadata) -> Boolean>()
    val date = filterCollection.get(VcsLogFilterCollection.DATE_FILTER)
    date?.after?.let { after ->
    filters.add {
    it.date.isAfter(after.toInstant().atZone(ZoneId.of("UTC")))
    }
    }
    date?.before?.let { before ->
    filters.add {
    it.date.isBefore(before.toInstant().atZone(ZoneId.of("UTC")))
    }
    }
    filterCollection.get(VcsLogFilterCollection.BRANCH_FILTER)?.let { filter ->
    channelFilters.add {
    filter.matches(it)
    }
    }
    filterCollection.get(VcsLogFilterCollection.REVISION_FILTER)?.let { filter ->
    filters.add {
    filter.heads.any { head ->
    it.asSha1Hash == head.hash.asString()
    }
    }
    }
    filterCollection.get(VcsLogFilterCollection.USER_FILTER)?.let { filter ->
    metadataFilters.add {
    filter.matches(it)
    }
    }
    filterCollection.get(VcsLogFilterCollection.HASH_FILTER)?.let { filter ->
    filters.add {
    filter.hashes.any { hash ->
    it.changeHash == hash || it.asSha1Hash == hash
    }
    }
    }
    filterCollection.get(VcsLogFilterCollection.TEXT_FILTER)?.let { filter ->
    filters.add {
    filter.matches(it.message)
    }
    }
    filterCollection.get(VcsLogFilterCollection.STRUCTURE_FILTER)?.let { filter ->
    filters.add {
    filter.files.any { filterRoot ->
    val filterRootPath = filterRoot.convertToNio()
    it.hunks.any { hunk ->
    (hunk is HunkWithPath) && hunk.resolvePath(rootPath).startsWith(filterRootPath)
    }
    }
    }
    }
    filterCollection.get(VcsLogFilterCollection.ROOT_FILTER)?.let { filter ->
    filters.add {
    filter.roots.any { filterRoot ->
    val filterRootPath = filterRoot.convertToNio()
    it.hunks.any { hunk ->
    (hunk is HunkWithPath) && hunk.resolvePath(rootPath).startsWith(filterRootPath)
    }
    }
    }
    }
    val records = mutableListOf<TimedVcsCommit>()
    createMetadataForEntries(this.project, root, {
    if (channelFilters.all { filter -> filter(it) }) {
    this.project.pijul().log(this.project, root.convertToNio(), it).result?.entries.orEmpty()
    .filter { filters.all { filter -> filter(it) } }
    } else {
    emptyList()
    }
    }, { _, it ->
    if (fullDetailsFilters.all { filter -> filter(it) }) {
    val meta = createMetadata(project, root, it)
    if (metadataFilters.all { filter -> filter(meta) }) {
    records += meta
    }
    }
    })
    return records
    }
    override fun getCurrentUser(root: VirtualFile): VcsUser? {
    return null
    }
    override fun getContainingBranches(root: VirtualFile, commitHash: Hash): MutableCollection<String> {
    val channels = mutableListOf<String>()
    createMetadataForEntries(this.project, root, {
    this.project.pijul().log(this.project, root.convertToNio(), it).result?.entries.orEmpty().filter {
    DigestUtils.sha1Hex(it.changeHash) == commitHash.asString()
    }
    }, { c, it ->
    channels += c
    })
    return channels
    }
    override fun <T : Any?> getPropertyValue(property: VcsLogProperties.VcsLogProperty<T>?): T? {
    if (property == VcsLogProperties.HAS_COMMITTER) {
    return true as T
    }
    return null
    }
    override fun getVcsRoot(project: Project, detectedRoot: VirtualFile, filePath: FilePath): VirtualFile? {
    return Pijul.findPijulDirectory(detectedRoot)
    }
    override fun getCurrentBranch(root: VirtualFile): String? {
    return this.project.pijul().channel(this.project, root).result?.channels?.firstOrNull { it.current }?.name
    }
    companion object {
    fun createMetadata(
    project: Project,
    root: VirtualFile,
    fetcher: (channel: String) -> List<PijulLogEntry>
    ): VcsLogProvider.DetailedLogData {
    val commits = mutableListOf<VcsCommitMetadata>()
    val log = createMetadata(project, root, fetcher) {
    commits.add(it)
    }
    return LogDataImpl(log.refs, commits)
    }
    fun createMetadataForEntries(
    project: Project,
    root: VirtualFile,
    fetcher: (channel: String) -> List<PijulLogEntry>,
    consumer: (channel: String, PijulLogEntryCommitDetails) -> Unit
    ): VcsLogProvider.LogData {
    val latest = project.pijul().latestRevisionNumber(project, root.convertToNio()).result?.hash
    val allChannels = project.pijul().channel(project, root.convertToNio()).result?.channels.orEmpty()
    val currentChannel = allChannels.firstOrNull {
    it.current
    }
    val refs = mutableSetOf<VcsRef>()
    val authors = mutableSetOf<VcsUser>()
    val rootPath = root.convertToNio()
    val factory = getObjectsFactoryWithDisposeCheck(project) ?: return LogDataImpl.empty()
    allChannels.forEach { channel ->
    val allTags = if (channel.current) {
    // Only current tag of current channel is available through `pijul tag` ATM
    project.pijul().tags(project, root.convertToNio()).result.orEmpty()
    } else {
    emptyList()
    }
    allTags.forEach {
    val hash = HashImpl.build(DigestUtils.sha1Hex(it.hash))//PijulHash(it.hash)
    val ref = factory.createRef(hash, it.simpleMessage, PijulVcsLogRefManager.TAG, root)
    if (!refs.contains(ref)) refs.add(ref)
    }
    var first = true
    fetcher(channel.name).forEach {
    val hash = HashImpl.build(DigestUtils.sha1Hex(it.changeHash))//PijulHash(it.changeHash)
    authors.addAll(it.authors.filter { it.name != null && it.email != null }
    .map { VcsUserImpl(it.name!!, it.email!!) })
    if (channel.current) {
    // Only current tag of current channel is available through `pijul tag` ATM
    val tag = allTags.singleOrNull()
    if (tag != null) {
    if (first) {
    val ref = factory.createRef(hash, tag.simpleMessage, PijulVcsLogRefManager.TAG, root)
    if (!refs.contains(ref)) refs.add(ref)
    }
    }
    }
    first = false
    if (it.changeHash == latest) {
    val ref = factory.createRef(hash, "CURRENT", PijulVcsLogRefManager.CURRENT, root)
    if (!refs.contains(ref)) refs.add(ref)
    }
    val ref = factory.createRef(hash, channel.name, PijulVcsLogRefManager.CHANNEL, root)
    if (!refs.contains(ref)) refs.add(ref)
    val details = PijulLogEntryCommitDetails(
    rootPath,
    project,
    it,
    ) {
    val changes = mutableListOf<PijulCommittedChangeList>()
    pijul(project).changes(project, rootPath, it, 1, {
    true
    }) {
    changes += it
    }
    changes.single().changes.toList()
    }
    consumer(channel.name, details)
    }
    }
    return LogDataImpl(refs, authors)
    }
    fun createMetadata(
    project: Project,
    root: VirtualFile,
    fetcher: (channel: String) -> List<PijulLogEntry>,
    consumer: (VcsCommitMetadata) -> Unit
    ): VcsLogProvider.LogData {
    val factory = getObjectsFactoryWithDisposeCheck(project) ?: return LogDataImpl.empty()
    return createMetadataForEntries(project, root, fetcher) { _, it ->
    consumer(
    factory.createCommitMetadata(
    it.id,
    emptyList(),
    it.commitTime,
    root,
    it.subject,
    it.author.name,
    it.author.email,
    it.fullMessage,
    it.committer.name,
    it.committer.email,
    it.authorTime
    )
    )
    }
    }
    fun createMetadata(
    project: Project,
    root: VirtualFile,
    it: PijulLogEntryCommitDetails
    ): VcsCommitMetadata {
    val factory = getObjectsFactoryWithDisposeCheck(project)!!
    return factory.createCommitMetadata(
    it.id,
    emptyList(),
    it.commitTime,
    root,
    it.subject,
    it.author.name,
    it.author.email,
    it.fullMessage,
    it.committer.name,
    it.committer.email,
    it.authorTime
    )
    }
    fun getObjectsFactoryWithDisposeCheck(project: Project): VcsLogObjectsFactory? {
    return ReadAction.compute<VcsLogObjectsFactory?, RuntimeException> {
    if (!project.isDisposed) {
    return@compute project.getService(VcsLogObjectsFactory::class.java)
    }
    null
    }
    }
    }
    }
  • file addition: PijulLogEntryCommitDetails.kt (----------)
    [21.6847]
    package com.github.jonathanxd.dracon.log
    import com.intellij.openapi.project.Project
    import com.intellij.openapi.vcs.changes.Change
    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.HashImpl
    import com.intellij.vcs.log.impl.VcsUserImpl
    import org.apache.commons.codec.digest.DigestUtils
    import java.nio.file.Path
    class PijulLogEntryCommitDetails(
    val root: Path,
    val project: Project,
    val entry: PijulLogEntry,
    val changeRetriever: (String) -> List<Change>
    ) : VcsFullCommitDetails {
    override fun getId(): Hash =
    HashImpl.build(DigestUtils.sha1Hex(this.entry.changeHash))
    //PijulHash(this.entry.changeHash)
    override fun getParents(): MutableList<Hash> =
    //this.entry.dependencies.map { it.hash }.map(::PijulHash).toMutableList()
    this.entry.dependencies.map { it.hash }.map { DigestUtils.sha1Hex(it) }.map { HashImpl.build(it) }.toMutableList()
    fun getPijulParents(): List<PijulHash> =
    this.entry.dependencies.map { it.hash }.map(::PijulHash)
    override fun getTimestamp(): Long = this.entry.date.toInstant().toEpochMilli()
    override fun getRoot(): VirtualFile =
    VirtualFileManager.getInstance().findFileByNioPath(this.root)!!
    override fun getSubject(): String =
    if (this.entry.message.isEmpty()) ""
    else this.entry.message.split("\n").first { it.trim().isNotEmpty() }
    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.changeHash).toMutableList()
    override fun getChanges(parent: Int): MutableCollection<Change> =
    this.changeRetriever(this.parents[parent].asString()).toMutableList()
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 6
    [3.2317]
    [3.61076]
    import org.apache.commons.codec.digest.DigestUtils
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 12
    [3.2112]
    [3.2112]
    import java.time.format.DateTimeFormatterBuilder
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 14
    [3.2150]
    [3.2150]
    import java.time.temporal.ChronoField
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 37
    [3.5061]
    [3.2153]
    val PijulLogEntry.asSha1Hash: String get() = DigestUtils.sha1Hex(this.changeHash)
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/log/PijulLog.kt at line 886
    [3.85041][3.3752:3844](),[3.3752][3.3752:3844]()
    val RFC3339_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSSSSSSSS]XXX")
    [3.85041]
    [3.3844]
    val RFC3339_FORMATTER = DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd'T'HH:mm:ss")
    .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true)
    .appendOffsetId()
    .toFormatter()
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/ignore/IgnoreUtil.kt at line 30
    [3.19138]
    [3.19138]
    }
    }
    fun isIgnored(root: Path, file: Path): Boolean {
    val ignore = root.resolve(".ignore")
    return if (Files.exists(ignore) && Files.isRegularFile(ignore)) {
    val lines = Files.readAllLines(ignore, Charsets.UTF_8)
    val paths = lines.map { path ->
    root.resolve(path)
    }
    paths.any { path -> file.startsWith(path) }
    } else {
    false
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/content/PijulContentRevision.kt at line 42
    [22.6090]
    [22.7808]
    override fun toString(): String =
    "PijulContentRevision(${this.revision.hash})"
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/config/PijulSettings.kt at line 5
    [2.2696]
    [3.5431]
    import com.intellij.dvcs.branch.DvcsBranchSettings
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/config/PijulSettings.kt at line 10
    [3.5625]
    [3.5625]
    import com.intellij.util.xmlb.annotations.Property
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/config/PijulSettings.kt at line 52
    [3.6170]
    [3.6170]
    fun getChannelSettings(): DvcsBranchSettings =
    this.state.channelSettings
    fun setChannelSettings(settings: DvcsBranchSettings) {
    this.state.channelSettings = settings
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/config/PijulSettings.kt at line 89
    [3.6894]
    [3.6894]
    @get:OptionTag("CHANNEL_SETTINGS")
    @get:Property(surroundWithTag = false, flat = true)
    var channelSettings by property(DvcsBranchSettings())
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 35
    [3.41164]
    [3.4157]
    import com.github.jonathanxd.dracon.revision.ChannelRevision
    import com.github.jonathanxd.dracon.revision.ChannelRevisions
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 598
    [3.16343]
    [3.16343]
    override fun tags(project: Project, root: Path): PijulOperationResult<List<PijulTag>> {
    val result = this.doExecutionWithMapperEvenFailed("tag", this.createPainlessExecPijulOperation(project, root, listOf("tag"))) {
    it.parseTags()
    }
    if (result.result != null && result.result.isNotEmpty()) { // Force success because Pijul is failing with `Not a directory` even in success case.
    return PijulOperationResult("tag", SuccessStatusCode, result.result)
    } else {
    return result
    }
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 646
    [22.11222]
    [3.16697]
    override fun log(project: Project, root: Path, channel: String): PijulOperationResult<PijulLog> {
    val logHashExecution = this.createPainlessExecPijulOperation(project, root, listOf("log", "--hash-only", "--channel", channel))
    val hashes = this.doExecutionWithMapper("log--hash-only", logHashExecution) {
    it.lines()
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 655
    [3.16698]
    [3.16698]
    if (hashes.statusCode !is SuccessStatusCode) {
    return hashes as PijulOperationResult<PijulLog>
    } else {
    val entries = mutableListOf<PijulLogEntry>()
    for (hash in hashes.result!!) {
    if (hash.isEmpty()) {
    break
    }
    val change = this.pijulLogEntryCache.load(hash) {
    this.doExecutionWithMapper(
    "change-$hash",
    this.createPainlessExecPijulOperation(project, root, listOf("change", hash))
    ) {
    it.parseChange(hash)
    }
    }
    if (change.statusCode !is SuccessStatusCode) {
    return change as PijulOperationResult<PijulLog>
    } else if (change.result != null) {
    entries += change.result
    }
    }
    return PijulOperationResult(hashes.operation, hashes.statusCode, PijulLog(entries))
    }
    }
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 918
    [3.19677]
    [3.7899]
    override fun revisionByChannel(project: Project, root: Path): PijulOperationResult<ChannelRevisions> {
    return this.channel(project, root).flatMap {
    val mapped = it.channels.map { ch ->
    this.log(project, root, ch.name).map {
    it.entries.firstOrNull()?.let {
    ChannelRevision(ch.name, PijulRevisionNumber(it.changeHash, it.date))
    }
    }
    }
    for (m in mapped) {
    if (m.result == null)
    return@flatMap m as PijulOperationResult<ChannelRevisions>
    }
    PijulOperationResult(
    "revision by channel",
    SuccessStatusCode,
    ChannelRevisions(mapped.map { it.result!! })
    )
    }
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 981
    [3.20085][3.2977:3095]()
    else ChannelInfo(channels.filter { it.isNotEmpty() }.map { PijulChannel(it[0] == '*', it.substring(1)) })
    [3.20085]
    [3.20176]
    else ChannelInfo(channels.filter { it.isNotEmpty() }.map {
    val name = it.substring(1)
    val effectiveName = if (name.startsWith(" ")) name.substring(1) else name
    PijulChannel(it[0] == '*', effectiveName)
    })
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 1030
    [3.9882]
    [3.3401]
    val std = execution.regularStream
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cmd/PijulCmd.kt at line 1033
    [3.10017][3.10017:10125]()
    PijulOperationResult(name, NonZeroExitStatusCode(status, error), regularStreamStringMapper(""))
    [3.10017]
    [3.4582]
    PijulOperationResult(name, NonZeroExitStatusCode(status, error), regularStreamStringMapper(std))
  • file addition: PijulChannelType.kt (----------)
    [3.23216]
    package com.github.jonathanxd.dracon.channel
    import com.intellij.dvcs.branch.BranchType
    enum class PijulChannelType(private val nname: String) : BranchType {
    CHANNEL("CHANNEL");
    override fun getName(): String = this.nname
    }
  • file addition: PijulChannelManager.kt (----------)
    [3.23216]
    package com.github.jonathanxd.dracon.channel
    import com.github.jonathanxd.dracon.config.PijulSettings
    import com.intellij.dvcs.branch.BranchType
    import com.intellij.dvcs.branch.DvcsBranchManager
    import com.intellij.openapi.components.Service
    import com.intellij.openapi.project.Project
    @Service
    class PijulChannelManager(val project: Project) : DvcsBranchManager(
    project,
    PijulSettings.instance.getChannelSettings(),
    PijulChannelType.values()
    ) {
    override fun getDefaultBranchName(type: BranchType): String? =
    when (type) {
    PijulChannelType.CHANNEL -> "main"
    else -> null
    }
    }
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 89
    [3.23548][3.23548:23603]()
    entry.date.toEpochSecond() < beforeRev
    [3.23548]
    [3.23603]
    entry.date.toInstant().toEpochMilli() < beforeRev
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/changes/PijulCommittedChangesProvider.kt at line 95
    [3.23694][3.23694:23748]()
    entry.date.toEpochSecond() > afterRev
    [3.23694]
    [3.23748]
    entry.date.toInstant().toEpochMilli() > afterRev
  • edit in src/main/kotlin/com/github/jonathanxd/dracon/cache/FileRevisionCache.kt at line 9
    [3.30087]
    [3.14626]
    import com.github.jonathanxd.dracon.util.pijul
    import com.github.jonathanxd.dracon.util.pijulVcs
  • replacement in src/main/kotlin/com/github/jonathanxd/dracon/cache/FileRevisionCache.kt at line 40
    [3.15207][3.21077:21078](),[3.30883][3.21077:21078](),[3.21077][3.21077:21078]()
    [3.15207]
    [3.15208]
    project.pijul()
  • replacement in gradle.properties at line 14
    [3.12944][3.16867:16898]()
    platformVersion = 211.6693.111
    [3.12944]
    [3.12971]
    platformVersion = 211.7142.45
  • file addition: Dracon-0.1.0-NIGHTLY-BUILD-4.zip (----------)
    [23.10]
  • file addition: Dracon-0.1.0-NIGHTLY-BUILD-3.zip (----------)
    [23.10]
  • file addition: Dracon-0.1.0-NIGHTLY-BUILD-2.zip (----------)
    [23.10]
  • file addition: Dracon-0.1.0-NIGHTLY-BUILD-1.zip (----------)
    [23.10]