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

org.icroco.cococha.generator.ChangelogGenerator.kt Maven / Gradle / Ivy

There is a newer version: 1.1.3
Show newest version
package org.icroco.cococha.generator

import com.samskivert.mustache.Mustache
import mu.KLogging
import org.icroco.cococha.generator.git.GitService
import org.icroco.cococha.generator.git.VersionTag
import java.io.FileReader
import java.io.InputStreamReader
import java.io.Reader
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.nio.file.StandardOpenOption
import java.util.regex.Pattern

val defaultIssueRegex: Pattern = Pattern.compile("(([Cc][Ll][Oo][Ss][Ee][Ss][ \t]*:[ \t]*)?#(?\\d+))",
                                                 Pattern.DOTALL)

data class GeneratorParams(var template: Path?,
                           var overrideExisting: Boolean = false,
                           var appendToStart: Boolean = false,
                           var releaseName: String?,
                           val outputFile: String?,
                           val releaseCount: Int = 1,
                           val filterCommitType: List = listOf(CommitType.BUG_FIX,
                                                                           CommitType.FEAT,
                                                                           CommitType.PERFORMANCE),
                           val addCommitLink: Boolean = true,
                           val gitCommitUrl: String? = null,
                           val addIssueLink: Boolean = true,
                           val issueUrl: String? = null,
                           val IssueIdRegex: Pattern = defaultIssueRegex) {
    fun getTemplateReader(): Reader {
        val t = template?.let {
            if (!Files.exists(it)) {
                throw IllegalArgumentException("Template file doesn't exist: '$it'")
            }
            it
        }
        return if (t == null) InputStreamReader(ChangelogGenerator::class.java.getResourceAsStream(("/CHANGELOG.mustache")))
        else FileReader(t.toFile())
    }
}

class ChangelogGenerator(private val params: GeneratorParams) {
    private companion object : KLogging()

    private val gitService = GitService()

    fun run() {
        params.template = params.template?.let {
            if (!Files.exists(it)) {
                throw IllegalArgumentException("Template file doesn't exist: '$it'")
            }
            it
        }
        var tags = gitService.getTags()
        if (params.releaseCount >= 1) {
            tags = tags.take(params.releaseCount)
        }

        params.releaseName = buildReleaseName(tags)
        val gitUrl = if (params.addCommitLink) params.gitCommitUrl
                ?: gitService.getGitRemoteUrl() + "/commit/" else null
        val issueUrl = if (params.addIssueLink) params.issueUrl
                ?: gitService.getGitRemoteUrl() + "/issues/" else null

        val path: Path? = if (params.outputFile != null) Paths.get(params.outputFile).toAbsolutePath() else null
        logger.info { "Output file is: '${path?.toAbsolutePath() ?: "stdout"}'" }
        logger.info { "Output override existing is: '${params.overrideExisting}'" }
        logger.info { "Output append at start: '${params.appendToStart}'" }
        logger.info { "Release name is: '${params.releaseName}'" }
        logger.info { "Release Count is: '${params.releaseCount}'" }
        logger.info { "Filter commit log with: '${params.filterCommitType.joinToString(",") { it.prefix }}'" }
        logger.info { "Git commit URL: '${if (params.addCommitLink) gitUrl else "Disabled"}'" }
        logger.info { "Issue URL: '${if (params.addIssueLink) (issueUrl ?: "None") else "Disabled"}'" }
        logger.info { "Issue ID Regex: '${params.IssueIdRegex.pattern() ?: "None"}'" }
        val template = Mustache.compiler().compile(params.getTemplateReader())
        val releases = gitService.parseCommit(params.releaseName!!,
                                              tags,
                                              params.releaseCount,
                                              params.filterCommitType,
                                              params.IssueIdRegex)
        val md = template.execute(Releases(releases, gitUrl, issueUrl))

        if (path == null) {
            println("--------------- CHANGELOG BEGIN ------------------")
            println(md)
            println("----------------CHANGELOG END -----------------")
        } else {
            if (params.appendToStart && params.overrideExisting) {
                throw IllegalArgumentException("Option to override and append are exclusive, both cannot be true")
            }
            if (path.toFile().isDirectory) {
                throw IllegalArgumentException("Output cannot be a directory: '$path'")
            }
            if (Files.notExists(path.parent)) {
                throw IllegalArgumentException("Parent directory doesn't exist: '${path.parent.toAbsolutePath()}'")
            }
            if (Files.exists(path) && !params.overrideExisting) {
                throw IllegalArgumentException("File: '${path.toAbsolutePath()}' already exists. Set the right option to force overriding or change filename")
            }
            if (Files.exists(path) && params.appendToStart) {
                val previousFile = Files.readString(path)
                Files.writeString(path, md + """
                    -----
                    
                """.trimIndent(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)
                Files.writeString(path, previousFile, StandardOpenOption.CREATE, StandardOpenOption.APPEND)
            } else {
                Files.writeString(path,
                                  md,
                                  StandardOpenOption.CREATE,
                                  StandardOpenOption.TRUNCATE_EXISTING)
            }
            logger.info { "Generation finished: ${path.toAbsolutePath() ?: "stdout"}" }
        }
    }

    private fun buildReleaseName(tags: List): String {
        return params.releaseName
                ?: if (tags.isEmpty()) VersionTag(0, 0, 1).toString()
                else tags.first().nextVersion().toString()
    }
}






© 2015 - 2025 Weber Informatics LLC | Privacy Policy