blob: ee84faad457b0fd592aebf394893c6b52145354d [file] [log] [blame]
package generator
import groovy.json.JsonSlurper
import model.Changelog
import model.Issue
import java.util.regex.Pattern
class ChangelogParser {
private static final String JIRA_SERVER = 'https://issues.apache.org/jira'
private static final String PROJECT_NAME = 'GROOVY'
private static final String PROJECT_ID = '12318123'
private static final String LOGNOTES_INTRO = /Release Notes - Groovy/
private static final String LOGNOTES_END = /<\/textarea>/
private static final String BUGTYPE_MARK = '** '
private static final String ITEM_MARK = ' * '
private static final Pattern ITEM_PATTERN = ~/\[(GROOVY-[0-9]+)\] - (.+)/
private static final String VERSION_PATTERN = /^((1\.)|[23]\.)/
static List<Changelog> fetchReleaseNotes(File cacheDirectory) {
def slurper = new JsonSlurper()
def versions = slurper.parse("$JIRA_SERVER/rest/api/2/project/$PROJECT_NAME/versions".toURL())
def versionMap = versions.findAll {
it.name =~ VERSION_PATTERN &&
it.released == true
}.collectEntries {
[fixName(it.name), it.id]
}
def raw = versionMap.collect { name, id ->
println "Fetching changelog for version $name"
new Changelog(groovyVersion: name, issues: changelogHTML(id, cacheDirectory))
}
createAggregates(raw, versionMap.keySet())
}
private static String fixName(String name) {
String id = name
String classifier = ''
int idx = name.indexOf('-')
if (idx>0) {
classifier = name.substring(idx)
id = name - classifier
}
if (id.count('.')<2) {
// groovy 2.0 instead of 2.0.0
id = "${id}.0"
}
"$id$classifier"
}
private static List<Changelog> createAggregates(final List<Changelog> changelogs, final Set<String> releasedVersions) {
def allMajor = changelogs.groupBy {
def v = it.groovyVersion
v.contains('-')?v-v.substring(v.indexOf('-')):v
}.findAll { ver, logs -> ver in releasedVersions }
allMajor.collect { k,v ->
def changelog = changelogs.find { it.groovyVersion == k }
if (!changelog) {
println "Not found: $k"
changelog = new Changelog(groovyVersion: k, issues:[])
changelogs << changelog
}
v.each {
changelog.issues = [*changelog.issues, *it.issues].unique().sort { it.id }
}
}
changelogs
}
private static List<Issue> changelogHTML(String id, File cacheDir) {
def cache = new File(cacheDir, "changelog-${id}.html")
def log
if (cache.exists()) {
log = cache.getText('UTF-8')
} else {
log = new URL("$JIRA_SERVER/secure/ReleaseNote.jspa?version=$id&styleName=Text&projectId=$PROJECT_ID").getText('UTF-8')
cache.write(log, 'UTF-8')
}
boolean inNotes = false
String type = null
List<Issue> issues = []
log.eachLine { line ->
if (line.startsWith(LOGNOTES_INTRO)) {
inNotes = true
} else if (line.startsWith(LOGNOTES_END)) {
inNotes = false
} else if (inNotes) {
if (line.startsWith(BUGTYPE_MARK)) {
type = line - BUGTYPE_MARK
} else if (line.startsWith(ITEM_MARK)) {
def m = ITEM_PATTERN.matcher(line)
m.find()
issues << new Issue(id: m.group(1), description: m.group(2), type: type)
}
}
}
issues
}
}