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

com.shakelang.shake.util.changelog.changelogs.kt Maven / Gradle / Ivy

package com.shakelang.shake.util.changelog

import com.shakelang.shake.util.markdown.MutableMarkdownDocument
import com.shakelang.shake.util.shason.elements.JsonObject
import com.shakelang.shake.util.shason.json

class ChangelogVersion(
    val version: Version,
    val changes: List
) {
    fun toObject(): Map {
        val map = mutableMapOf()
        map["version"] = version.toString()
        map["changes"] = changes
        return map
    }

    companion object {
        fun fromObject(obj: JsonObject): ChangelogVersion {
            if (!obj.containsKey("version")) throw IllegalArgumentException("ChangelogVersion object has no version")
            if (!obj.containsKey("changes")) throw IllegalArgumentException("ChangelogVersion object has no changes")

            val versionElement = obj["version"]!!
            val changesElement = obj["changes"]!!

            if (!versionElement.isJsonPrimitive() || !versionElement.toJsonPrimitive().isString()) {
                throw IllegalArgumentException("ChangelogVersion version is not a string")
            }
            if (!changesElement.isJsonArray()) {
                throw IllegalArgumentException("ChangelogVersion changes is not an array")
            }

            val version = Version.fromString(versionElement.toJsonPrimitive().toStringElement().value)
            val changes = changesElement.toJsonArray().map { it.toJsonPrimitive().toStringElement().value }

            return ChangelogVersion(version, changes)
        }
    }
}

class PackageChangelog(
    val path: String,
    val name: String,
    val description: String,
    val versions: MutableList = mutableListOf()
) {

    val folderPath: String
        get() = path.replace(":", "/").substring(1)

    val latestRelease: ChangelogVersion?
        get() {
            if (versions.isEmpty()) return null
            return versions.last()
        }

    val changedSinceLastRelease: Boolean
        get() {
            val latestRelease = latestRelease ?: return true
            return Changelog.instance.dirChangedSinceTag(
                tagRef("release/$folderPath/v${latestRelease.version}"),
                folderPath
            )
        }

    val latestReleaseVersion: Version
        get() {
            val latestRelease = latestRelease ?: return Version(0, 0, 0, "SNAPSHOT")
            return latestRelease.version
        }

    val latestReleaseWasSnapshot: Boolean
        get() {
            return latestReleaseVersion.suffix != ""
        }

    fun addVersion(version: ChangelogVersion) = versions.add(version)
    fun add(version: ChangelogVersion) = addVersion(version)

    fun toObject(): Map {
        val map = mutableMapOf()
        map["path"] = path
        map["name"] = name
        map["description"] = description
        map["versions"] = versions.map { it.toObject() }
        return map
    }

    companion object {
        fun fromObject(obj: JsonObject): PackageChangelog {
            if (!obj.containsKey("path")) throw IllegalArgumentException("PackageChangelog object has no path")
            if (!obj.containsKey("name")) throw IllegalArgumentException("PackageChangelog object has no name")
            if (!obj.containsKey("description")) throw IllegalArgumentException("PackageChangelog object has no description")
            if (!obj.containsKey("versions")) throw IllegalArgumentException("PackageChangelog object has no versions")

            val pathElement = obj["path"]!!
            val nameElement = obj["name"]!!
            val descriptionElement = obj["description"]!!
            val versionsElement = obj["versions"]!!

            if (!pathElement.isJsonPrimitive() || !pathElement.toJsonPrimitive().isString()) {
                throw IllegalArgumentException("PackageChangelog path is not a string")
            }
            if (!nameElement.isJsonPrimitive() || !nameElement.toJsonPrimitive().isString()) {
                throw IllegalArgumentException("PackageChangelog name is not a string")
            }
            if (!descriptionElement.isJsonPrimitive() || !descriptionElement.toJsonPrimitive().isString()) {
                throw IllegalArgumentException("PackageChangelog description is not a string")
            }
            if (!versionsElement.isJsonArray()) {
                throw IllegalArgumentException("PackageChangelog versions is not an array")
            }

            val path = pathElement.toJsonPrimitive().toStringElement().value
            val name = nameElement.toJsonPrimitive().toStringElement().value
            val description = descriptionElement.toJsonPrimitive().toStringElement().value
            val versions = versionsElement.toJsonArray().map { ChangelogVersion.fromObject(it.toJsonObject()) }

            return PackageChangelog(path, name, description, versions.toMutableList())
        }
    }
}

class ChangelogMap(
    val packages: MutableList
) {

    fun toObject(): Map {
        val map = mutableMapOf()
        map["packages"] = packages.map { it.toObject() }
        return map
    }

    fun add(it: PackageChangelog) = packages.add(it)

    companion object {
        fun fromObject(obj: JsonObject): ChangelogMap {
            if (!obj.containsKey("packages")) throw IllegalArgumentException("ChangelogMap object has no packages")

            val packagesElement = obj["packages"]!!

            if (!packagesElement.isJsonArray()) {
                throw IllegalArgumentException("ChangelogMap packages is not an array")
            }

            val packages = packagesElement.toJsonArray().map { PackageChangelog.fromObject(it.toJsonObject()) }

            return ChangelogMap(packages.toMutableList())
        }

        fun fromString(string: String): ChangelogMap {
            val obj = json.parse(string)
            if (!obj.isJsonObject()) throw IllegalArgumentException("ChangelogMap is not a json object")
            return fromObject(obj.toJsonObject())
        }
    }
}

fun Changelog.readMap(): ChangelogMap {
    val file = project.file(".changelog/changelogs.json")
    if (!file.exists()) {
        return ChangelogMap(
            readStructure().map {
                PackageChangelog(
                    it.path,
                    it.name,
                    it.description
                )
            }.toMutableList()
//        mutableListOf()
        )
    }
    return ChangelogMap.fromString(file.readText())
}

fun Changelog.writeMap(map: ChangelogMap) {
    val file = project.file(".changelog/changelogs.json")
    file.writeText(json.stringify(map.toObject(), true))
}

fun Changelog.renderChangelog(map: PackageChangelog): String {
    return MutableMarkdownDocument {
        h1(map.name)
        h2("Description")
        p(map.description)
        h2("Versions")
        map.versions.forEach { version ->
            h3(version.version.toString())
            version.changes.forEach { change ->
                p(change)
            }
        }
    }.render()
}

fun Changelog.renderChangelog(map: ChangelogMap) {
    map.packages.forEach { pkg ->
        // get project for path
        val project = Changelog.instance.project.project(pkg.path)
        val file = project.file("CHANGELOG.md")
        file.writeText(renderChangelog(pkg))
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy