Skip to content

Commit

Permalink
Merge pull request #4 from CalMWolfs/edits
Browse files Browse the repository at this point in the history
  • Loading branch information
CalMWolfs authored Oct 9, 2024
2 parents 4e155e1 + 79eb5cb commit 08c68d0
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 73 deletions.
123 changes: 62 additions & 61 deletions src/main/kotlin/at/hannibal2/changelog/ContributorsBuilder.kt
Original file line number Diff line number Diff line change
@@ -1,86 +1,87 @@
package org.example
package at.hannibal2.changelog

import at.hannibal2.changelog.Utils.matchMatcher
import java.awt.Toolkit
import java.awt.datatransfer.DataFlavor

/**
* This script expects the raw content of the full version in question
* from CHANGELOG.MD in clipboard and will print the alphabetically orderd list of all contributrs.
* from CHANGELOG.MD in clipboard and will print the alphabetically ordered list of all contributors.
* This also supports entries with multiple contributors
*/

fun main() {
val clipboard = Toolkit.getDefaultToolkit().systemClipboard?.getData(DataFlavor.stringFlavor)?.toString()
if (clipboard == null) {
println("clipboard empty")
return
}
// remove sub categories
var s = clipboard.split("\n").toList().filter { !it.startsWith(" + ") && !it.startsWith(" ") }
.joinToString("\n")
object ContributorsBuilder {

// fix unecessary break points
s = s.replace("\n ", " ").replace(" ", " ")
private val contributionPattern = "\\+ .*\\. - (?<name>.*) \\(.*\\)".toPattern()

val pattern = "\\+ .*\\. - (?<name>.*) \\(.*\\)".toPattern()
fun getContributors(text: String) {

val map = mutableMapOf<String, Int>()
// Remove sub-categories and fix unnecessary break points
val content = text.split("\n")
.filter { !it.startsWith(" + ") && !it.startsWith(" ") }
.joinToString("\n")
.replace("\n ", " ")
.replace(" ", " ")

for (line in s.split("\n")) {
val matcher = pattern.matcher(line)
if (matcher.matches()) {
val name = matcher.group("name")
val names = mutableListOf<String>()
if (name.contains(", ")) {
names.addAll(name.split(", "))
} else if (name.contains(" & ")) {
names.addAll(name.split(" & "))
} else if (name.contains(" + ")) {
names.addAll(name.split(" + "))
} else if (name.contains("/")) {
names.addAll(name.split("/"))
} else {
names.add(name)
}
if (name == "Alexia Alexia Luna") {
println("line: $line")
val contributions = mutableMapOf<String, Int>()

for (line in content.split("\n")) {

contributionPattern.matchMatcher(line) {
val name = group("name")
val names = mutableListOf<String>()
if (name.contains(", ")) {
names.addAll(name.split(", "))
} else if (name.contains(" & ")) {
names.addAll(name.split(" & "))
} else if (name.contains(" + ")) {
names.addAll(name.split(" + "))
} else if (name.contains("/")) {
names.addAll(name.split("/"))
} else {
names.add(name)
}
for (oneName in names) {
contributions[oneName] = contributions.getOrDefault(oneName, 0) + 1
}
}
}
// printNumbers(map)
printFormatted(contributions.keys)
}

for (oneName in names) {
val old = map[oneName] ?: 0
map[oneName] = old + 1
private fun printFormatted(names: MutableSet<String>) {
println("")
val sorted = names.map { it to it.lowercase() }.sortedBy { it.second }.map { it.first }
val line = StringBuilder()
val total = StringBuilder()
for (name in sorted) {
line.append(name)
if (line.length > 35) {
total.append(line)
total.append("\n")
line.setLength(0)
} else {
line.append(", ")
}
} else {
if (line.startsWith("##")) continue
if (line == "") continue
}
println(" ")
println(total)
}
// printNumbers(map)
printFormatted(map.keys)
}

fun printFormatted(names: MutableSet<String>) {
println("")
val sorted = names.map { it to it.lowercase() }.sortedBy { it.second }.map { it.first }
val line = StringBuilder()
val total = StringBuilder()
for (name in sorted) {
line.append(name)
if (line.length > 35) {
total.append(line)
total.append("\n")
line.setLength(0)
} else {
line.append(", ")
private fun printNumbers(map: MutableMap<String, Int>) {
println("")
for ((name, amount) in map.entries.sortedBy { it.value }.reversed()) {
println("$name ($amount)")
}
}
println(" ")
println(total)
}

private fun printNumbers(map: MutableMap<String, Int>) {
println("")
for ((name, amount) in map.entries.sortedBy { it.value }.reversed()) {
println("$name ($amount)")
fun main() {
val clipboard = Toolkit.getDefaultToolkit().systemClipboard?.getData(DataFlavor.stringFlavor)?.toString()
if (clipboard == null) {
println("clipboard empty")
return
}
ContributorsBuilder.getContributors(clipboard)
}
41 changes: 31 additions & 10 deletions src/main/kotlin/at/hannibal2/changelog/SkyHanniChangelogBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ object SkyHanniChangelogBuilder {

if (changeErrors.isNotEmpty()) {
println("PR has errors: ${pullRequest.prInfo()}")
changeErrors.forEach { println(" - ${it.message}${it.formatLine()}") }
changeErrors.forEach { println(" - ${it.formatLine()}") }
println()
wrongPrDescription++
continue
Expand Down Expand Up @@ -229,19 +229,26 @@ object SkyHanniChangelogBuilder {
}

prTitlePattern.matchMatcher(prTitle) {
val prPrefixes = group("prefix").split(" + ")
val prefixText = group("prefix")

if (prefixText.contains("/") || prefixText.contains("&")) {
errors.add(PullRequestNameError("PR categories shouldn't be separated by '/' or '&', use ' + ' instead"))
}

val prPrefixes = prefixText.split(Regex("[+&/]")).map { it.trim() }
val expectedCategories = changes.map { it.category }.toSet()
val expectedOptions = expectedCategories.joinToString { it.prPrefix }

val foundCategories = prPrefixes.mapNotNull { prefix ->
PullRequestCategory.fromPrPrefix(prefix) ?: run {
errors.add(PullRequestNameError("Unknown category: '$prefix', valid categories are: ${PullRequestCategory.validCategories()}"))
errors.add(PullRequestNameError("Unknown category: '$prefix', valid categories are: ${PullRequestCategory.validCategories()} " +
"and expected categories based on your changes are: $expectedOptions"))
null
}
}

foundCategories.forEach { category ->
if (category !in expectedCategories) {
val expectedOptions = expectedCategories.joinToString { it.prPrefix }
errors.add(PullRequestNameError("PR has category '${category.prPrefix}' which is not in the changelog. Expected categories: $expectedOptions"))
}
}
Expand Down Expand Up @@ -352,22 +359,36 @@ class CodeChange(val text: String, val category: PullRequestCategory, val prLink
}

class ChangelogError(val message: String, private val relevantLine: String) {
fun formatLine() = if (relevantLine.isBlank()) "" else " in text: `$relevantLine`"
fun formatLine(): String {
val lineText = if (relevantLine.isBlank()) "" else " in text: `$relevantLine`"
return "$message$lineText"
}
}

class PullRequestNameError(val message: String)

class UpdateVersion(fullVersion: String, betaVersion: String) {
val asTitle = "Version $fullVersion Beta $betaVersion"
val asTag = "$fullVersion.Beta.$betaVersion"
// Not having a full version can be used for creating the changelog between the final beta and the full version
class UpdateVersion(fullVersion: String, betaVersion: String?) {
val asTitle = "Version $fullVersion${betaVersion?.let { " Beta $it" } ?: ""}"
val asTag = "$fullVersion${betaVersion?.let { ".Beta.$it" } ?: ""}"

constructor(versionString: String) : this(extractVersion(versionString).first, extractVersion(versionString).second)

companion object {
private fun extractVersion(versionString: String): Pair<String, String?> {
val split = versionString.split(",").map { it.trim() }
val fullVersion = if (split[0].startsWith("0.")) split[0] else "0.${split[0]}"
val betaVersion = split.getOrNull(1)
return fullVersion to betaVersion
}
}
}

fun main() {
// todo maybe change the way version is handled
val version = UpdateVersion("0.27", "17")
val version = UpdateVersion("0.28", "1")
SkyHanniChangelogBuilder.generateChangelog(WhatToFetch.ALREADY_MERGED, version)
}

// smart AI prompt for formatting
// keep the formatting. just find typos and fix them in this changelog. also suggest slightly better wording if applicable. send me the whole text in one code block as output

18 changes: 16 additions & 2 deletions src/test/kotlin/SkyHanniChangelogBuilderTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ class SkyHanniChangelogBuilderTest {

@Test
fun `test title with correct pull request title`() {
val prTitle = "Feature: New feature"
val prTitle = "Feature + Fix: New feature"
val prLink = "https://example.com/pr/1"

val (changes, errors) = SkyHanniChangelogBuilder.findChanges(largeValidInput, prLink)
Expand All @@ -142,7 +142,8 @@ class SkyHanniChangelogBuilderTest {
val pullRequestTitleErrors = SkyHanniChangelogBuilder.findPullRequestNameErrors(prTitle, changes)

assertEquals(1, pullRequestTitleErrors.size, "Expected one error")
assertEquals("Unknown category: 'Bugfix', valid categories are: ${PullRequestCategory.validCategories()}", pullRequestTitleErrors[0].message)
assertEquals("Unknown category: 'Bugfix', valid categories are: ${PullRequestCategory.validCategories()} " +
"and expected categories based on your changes are: Feature, Fix", pullRequestTitleErrors[0].message)
}

@Test
Expand Down Expand Up @@ -170,4 +171,17 @@ class SkyHanniChangelogBuilderTest {
assertEquals(1, pullRequestTitleErrors.size, "Expected one error")
assertEquals("PR has category 'Backend' which is not in the changelog. Expected categories: Feature, Fix", pullRequestTitleErrors[0].message)
}

@Test
fun `test title with another wrong format`() {
val prTitle = "Feature/Fix: Fix up the backend"
val prLink = "https://example.com/pr/1"

val (changes, errors) = SkyHanniChangelogBuilder.findChanges(largeValidInput, prLink)

val pullRequestTitleErrors = SkyHanniChangelogBuilder.findPullRequestNameErrors(prTitle, changes)

assertEquals(1, pullRequestTitleErrors.size, "Expected one error")
assertEquals("PR categories shouldn't be separated by '/' or '&', use ' + ' instead", pullRequestTitleErrors[0].message)
}
}

0 comments on commit 08c68d0

Please sign in to comment.