All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gradle-plugins.changelog.0.1.0-alpha.26.source-code.com.javiersc.gradle.plugins.changelog.gradle.kts Maven / Gradle / Ivy

There is a newer version: 0.1.0-rc.45
Show newest version
@file:OptIn(ExperimentalStdlibApi::class)

import java.text.SimpleDateFormat
import java.util.Date
import org.jetbrains.changelog.ChangelogPluginExtension
import org.jetbrains.changelog.closure
import org.jetbrains.changelog.date
import org.jetbrains.changelog.tasks.PatchChangelogTask

plugins {
    id("org.jetbrains.changelog")
}

configure {
    version = "${project.version}"
    header = closure { "[$version] - ${date()}" }
    groups = listOf("Added", "Changed", "Deprecated", "Removed", "Fixed", "Updated")
}

tasks {
    named("patchChangelog") {
        doLast {
            improveChangelog()
        }
    }

    register("mergeChangelog") {
        doLast {
            if ("${project.version}".all { it.isDigit() || it == '.' }) {
                mergeChangelog("${project.version}")
            }
        }
    }
}

val changelogFile = file("$projectDir/CHANGELOG.md")
val changelogWithNoBlankLines
    get() = changelogFile.readLines().filter { it.isNotBlank() }

val h1Regex = Regex("""^(#)(\s)(.*)${'$'}""")
val unreleasedRegex = Regex("""^(##)(\s)(\[Unreleased\])(.*)${'$'}""")
val h2Regex = Regex("""^(##)(\s)(.*)${'$'}""")
val h3Regex = Regex("""^(###)(\s)(.*)${'$'}""")

fun improveChangelog() = changelogFile.writeText(buildChangelogAsString())

fun buildChangelog(): List =
    buildList {
            val lastReleaseIndex =
                changelogWithNoBlankLines.indexOfFirst {
                    !unreleasedRegex.matches(it) && h2Regex.matches(it)
                }

            addPreRelease(lastReleaseIndex)
            addRelease(lastReleaseIndex)
        }
        .filter(String::isNotBlank)

fun MutableList.addPreRelease(lastReleaseIndex: Int) {
    changelogWithNoBlankLines.subList(0, lastReleaseIndex).forEach { line ->
        when {
            h1Regex.matches(line) -> add(line)
            unreleasedRegex.matches(line) -> add(line)
            h2Regex.matches(line) -> add(line)
            h3Regex.matches(line) -> add(line)
            else -> add(line)
        }
    }
}

fun MutableList.addRelease(lastReleaseIndex: Int) {
    val releasesChangelog =
        changelogWithNoBlankLines.subList(lastReleaseIndex, changelogWithNoBlankLines.size)

    runCatching {
        releasesChangelog.onEachIndexed { index, line ->
            when {
                unreleasedRegex.matches(line) -> add(line)
                h1Regex.matches(line) -> add(line)
                h2Regex.matches(line) -> add(line)
                h3Regex.matches(line) &&
                    (h3Regex.matches(releasesChangelog[index + 1]) ||
                        h2Regex.matches(releasesChangelog[index + 1])) -> add("")
                h3Regex.matches(line) -> add(line)
                else -> add(line)
            }
        }
    }
        .onFailure { add("") }
}

fun buildChangelogAsString(): String =
    buildChangelog()
        .mapIndexed { index, line ->
            val nextLine = buildChangelog().getOrElse(index + 1) { "" }
            if (!unreleasedRegex.matches(line) && h2Regex.matches(line) && h2Regex.matches(nextLine)
            ) {
                "$line\n- No changes"
            } else {
                line
            }
        }
        .joinToString("\n") { line ->
            when {
                h1Regex.matches(line) -> line
                unreleasedRegex.matches(line) -> "\n$line"
                h2Regex.matches(line) -> "\n$line"
                h3Regex.matches(line) -> "\n$line"
                else -> line
            }
        }
        .replaceFirst("### Updated", "### Updated\n") + "\n"

fun mergeChangelog(version: String) {
    val changelog = changelogFile.readLines()

    val header = "## [$version] - ${SimpleDateFormat("yyyy-MM-dd").format(Date())}\n"

    fun String.containVersion(version: String): Boolean =
        contains("## [$version-") || contains("## [$version]")

    val firstVersionIndex = changelog.indexOfFirst { it.containVersion(version) }
    val lastVersionIndex = changelog.indexOfLast { it.containVersion(version) }

    val firstOldVersion =
        changelog.subList(lastVersionIndex + 1, changelog.count()).firstOrNull {
            it.contains("## [")
        }
    val firstOldVersionIndex =
        if (firstOldVersion != null) changelog.indexOf(firstOldVersion) else changelog.count()

    val versionBlock =
        if (firstOldVersionIndex == -1) changelog.subList(firstVersionIndex, firstOldVersionIndex)
        else changelog.subList(firstVersionIndex, firstOldVersionIndex)

    val mergedVersion = mutableListOf()
    mergedVersion.add(header)
    mergedVersion.addAll(extractAllBlocks(versionBlock))

    val mergedChangelog = mutableListOf()
    mergedChangelog.addAll(changelog.subList(0, firstVersionIndex - 1))
    mergedChangelog.add("")
    mergedChangelog.addAll(mergedVersion)
    mergedChangelog.addAll(changelog.subList(firstOldVersionIndex, changelog.count()))

    changelogFile.writeText(mergedChangelog.joinToString("\n"))
}

fun extractAllBlocks(versionBlock: List): List {

    val allBlocks = mutableListOf()

    extractBlock("Added", versionBlock).run { if (isNotEmpty()) allBlocks.addAll(this) }
    extractBlock("Changed", versionBlock).run { if (isNotEmpty()) allBlocks.addAll(this) }
    extractBlock("Deprecated", versionBlock).run { if (isNotEmpty()) allBlocks.addAll(this) }
    extractBlock("Removed", versionBlock).run { if (isNotEmpty()) allBlocks.addAll(this) }
    extractBlock("Fixed", versionBlock).run { if (isNotEmpty()) allBlocks.addAll(this) }
    extractBlock("Updated", versionBlock).run { if (isNotEmpty()) allBlocks.addAll(this) }

    return allBlocks
}

fun extractBlock(blockName: String, versionBlock: List): List {
    val block = mutableListOf()
    block.add("### $blockName")
    val indexes =
        versionBlock
            .mapIndexed { index, line -> if (line.contains("### $blockName")) index else null }
            .filterNotNull()

    for (i in indexes) {
        val changes = versionBlock.subList(i + 1, versionBlock.count())
        block.addAll(changes.takeWhile { it.replace(" ", "").startsWith("-") })
    }
    block.add("")

    return if (block.any { it.replace(" ", "").startsWith("-") }) block else emptyList()
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy