src/main/kotlin/de/uapcore/lightpit/vcs/VcsConnector.kt

Tue, 18 Jul 2023 18:05:49 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 18 Jul 2023 18:05:49 +0200
changeset 280
12b898531d1a
child 281
c15b9555ecf3
permissions
-rw-r--r--

add working Mercurial commit log parser

fixes #274

package de.uapcore.lightpit.vcs

import java.nio.file.Path
import java.util.concurrent.TimeUnit

abstract class VcsConnector(protected val path: String) {
    /**
     * Invokes the VCS binary with the given [args] and returns the output on stdout.
     */
    protected fun invokeCommand(workingDir: Path, vararg args : String): VcsConnectorResult<String> {
        return try {
            val command = mutableListOf(path)
            command.addAll(args)
            val process = ProcessBuilder(command).directory(workingDir.toFile()).start()
            val stdout = String(process.inputStream.readAllBytes(), Charsets.UTF_8)
            if (process.waitFor(30, TimeUnit.SECONDS)) {
                if (process.exitValue() == 0) {
                    VcsConnectorResult.Success(stdout)
                } else {
                    VcsConnectorResult.Error("VCS process did not return successfully.")
                }
            } else {
                VcsConnectorResult.Error("VCS process did not return in time.")
            }
        } catch (e: Throwable) {
            VcsConnectorResult.Error("Error during process invocation: "+e.message)
        }
    }

    /**
     * Takes a [commitLog] in format `::lpitref::{node}:{desc}` and parses commit references.
     * Supported references are (in this example, 47 is the issue ID):
     *  - fixes #47
     *  - fix #47
     *  - closes #47
     *  - close #47
     *  - relates to #47
     */
    protected fun parseCommitRefs(commitLog: String): List<CommitRef> = buildList {
        val marker = "::lpitref::"
        var currentHash = ""
        var currentDesc = ""
        for (line in commitLog.split("\n")) {
            // see if current line contains a new log entry
            if (line.startsWith(marker)) {
                val head = line.substring(marker.length).split(':', limit = 2)
                currentHash = head[0]
                currentDesc = head[1]
            }

            // skip possible preamble output
            if (currentHash.isEmpty()) continue

            // scan the lines for commit references
            Regex("""(?:relates to|fix(?:es)?|close(?:es)?) #(\d+)""")
                .findAll(line)
                .map { it.groupValues[1] }
                .map { it.toIntOrNull() }
                .filterNotNull()
                .forEach { commitId -> add(CommitRef(currentHash, commitId, currentDesc)) }
        }
    }
}

mercurial