Tue, 18 Jul 2023 18:05:49 +0200
add working Mercurial commit log parser
fixes #274
universe@280 | 1 | package de.uapcore.lightpit.vcs |
universe@280 | 2 | |
universe@280 | 3 | import java.nio.file.Path |
universe@280 | 4 | import java.util.concurrent.TimeUnit |
universe@280 | 5 | |
universe@280 | 6 | abstract class VcsConnector(protected val path: String) { |
universe@280 | 7 | /** |
universe@280 | 8 | * Invokes the VCS binary with the given [args] and returns the output on stdout. |
universe@280 | 9 | */ |
universe@280 | 10 | protected fun invokeCommand(workingDir: Path, vararg args : String): VcsConnectorResult<String> { |
universe@280 | 11 | return try { |
universe@280 | 12 | val command = mutableListOf(path) |
universe@280 | 13 | command.addAll(args) |
universe@280 | 14 | val process = ProcessBuilder(command).directory(workingDir.toFile()).start() |
universe@280 | 15 | val stdout = String(process.inputStream.readAllBytes(), Charsets.UTF_8) |
universe@280 | 16 | if (process.waitFor(30, TimeUnit.SECONDS)) { |
universe@280 | 17 | if (process.exitValue() == 0) { |
universe@280 | 18 | VcsConnectorResult.Success(stdout) |
universe@280 | 19 | } else { |
universe@280 | 20 | VcsConnectorResult.Error("VCS process did not return successfully.") |
universe@280 | 21 | } |
universe@280 | 22 | } else { |
universe@280 | 23 | VcsConnectorResult.Error("VCS process did not return in time.") |
universe@280 | 24 | } |
universe@280 | 25 | } catch (e: Throwable) { |
universe@280 | 26 | VcsConnectorResult.Error("Error during process invocation: "+e.message) |
universe@280 | 27 | } |
universe@280 | 28 | } |
universe@280 | 29 | |
universe@280 | 30 | /** |
universe@280 | 31 | * Takes a [commitLog] in format `::lpitref::{node}:{desc}` and parses commit references. |
universe@280 | 32 | * Supported references are (in this example, 47 is the issue ID): |
universe@280 | 33 | * - fixes #47 |
universe@280 | 34 | * - fix #47 |
universe@280 | 35 | * - closes #47 |
universe@280 | 36 | * - close #47 |
universe@280 | 37 | * - relates to #47 |
universe@280 | 38 | */ |
universe@280 | 39 | protected fun parseCommitRefs(commitLog: String): List<CommitRef> = buildList { |
universe@280 | 40 | val marker = "::lpitref::" |
universe@280 | 41 | var currentHash = "" |
universe@280 | 42 | var currentDesc = "" |
universe@280 | 43 | for (line in commitLog.split("\n")) { |
universe@280 | 44 | // see if current line contains a new log entry |
universe@280 | 45 | if (line.startsWith(marker)) { |
universe@280 | 46 | val head = line.substring(marker.length).split(':', limit = 2) |
universe@280 | 47 | currentHash = head[0] |
universe@280 | 48 | currentDesc = head[1] |
universe@280 | 49 | } |
universe@280 | 50 | |
universe@280 | 51 | // skip possible preamble output |
universe@280 | 52 | if (currentHash.isEmpty()) continue |
universe@280 | 53 | |
universe@280 | 54 | // scan the lines for commit references |
universe@280 | 55 | Regex("""(?:relates to|fix(?:es)?|close(?:es)?) #(\d+)""") |
universe@280 | 56 | .findAll(line) |
universe@280 | 57 | .map { it.groupValues[1] } |
universe@280 | 58 | .map { it.toIntOrNull() } |
universe@280 | 59 | .filterNotNull() |
universe@280 | 60 | .forEach { commitId -> add(CommitRef(currentHash, commitId, currentDesc)) } |
universe@280 | 61 | } |
universe@280 | 62 | } |
universe@280 | 63 | } |