портирован и слегка подправлен код из старого репозитория https://di9.ru/git/Voomra/Conventional-Commits
109 lines
4.3 KiB
Groovy
109 lines
4.3 KiB
Groovy
package ru.di9.gradle.commitlint
|
|
|
|
import org.gradle.api.DefaultTask
|
|
import org.gradle.api.InvalidUserDataException
|
|
import org.gradle.api.tasks.TaskAction
|
|
|
|
import java.nio.file.Files
|
|
import java.nio.file.Path
|
|
import java.util.regex.Pattern
|
|
|
|
class CommitLintTask extends DefaultTask {
|
|
private static final List<String> DEFAULT_TYPES = ["build", "docs", "add", "tweak", "fix", "remove", "revert", "perf", "refac", "style", "test"]
|
|
private static final List<String> DEFAULT_CONTEXTS = ["git", "ide"]
|
|
private static final List<String> DEFAULT_EXCLUDES = [Pattern.compile("^wip\$")]
|
|
private static final int DEFAULT_MAX_LINE = 72
|
|
private static final Path DEFAULT_COMMIT_MESSAGE_PATH = Path.of(".git/COMMIT_EDITMSG")
|
|
|
|
private static final List<Pattern> EXCLUDES = [
|
|
Pattern.compile("^rebase "),
|
|
Pattern.compile("^merge "),
|
|
]
|
|
private static final Pattern COMMIT_FIRST_LINE = Pattern.compile("^([a-z0-9]+?)!?(?:\\(([a-z0-9]+?)\\))?: .+\$")
|
|
|
|
private final Set<String> commitTypes = new HashSet<>()
|
|
private final Set<String> commitContexts = new HashSet<>()
|
|
private final Set<Pattern> commitExcludes = new HashSet<>()
|
|
private int commitMaxLength = 0
|
|
|
|
@TaskAction
|
|
void execute() throws IOException {
|
|
def ext = getProject().getExtensions()
|
|
.getByType(CommitLintExtension.class)
|
|
|
|
if (ext.types.isPresent()) {
|
|
commitTypes.addAll(ext.types.get().collect { it.toLowerCase() })
|
|
} else {
|
|
commitTypes.addAll(DEFAULT_TYPES)
|
|
}
|
|
|
|
if (ext.contexts.isPresent()) {
|
|
commitContexts.addAll(ext.contexts.get().collect { it.toLowerCase() })
|
|
} else {
|
|
commitContexts.addAll(DEFAULT_CONTEXTS)
|
|
}
|
|
|
|
commitExcludes.addAll(EXCLUDES)
|
|
if (ext.excludes.isPresent()) {
|
|
commitExcludes.addAll(ext.excludes.get().collect { Pattern.compile(it) })
|
|
} else {
|
|
commitExcludes.addAll(DEFAULT_EXCLUDES)
|
|
}
|
|
|
|
commitMaxLength = ext.maxLengthLine.getOrElse(DEFAULT_MAX_LINE)
|
|
|
|
Path gitCommitMessageFile
|
|
if (this.getProject().getProperties().containsKey("gitCommitMessageFile")) {
|
|
gitCommitMessageFile = Path.of((String) getProject().getProperties().get("gitCommitMessageFile"))
|
|
} else {
|
|
gitCommitMessageFile = DEFAULT_COMMIT_MESSAGE_PATH
|
|
}
|
|
|
|
def commitMessage = Files.readAllLines(getProject().rootDir.toPath().resolve(gitCommitMessageFile))
|
|
|
|
if (commitExcludes.any { it.matcher(commitMessage[0].toLowerCase()).find() }) {
|
|
return
|
|
}
|
|
|
|
validateFirstLine(commitMessage[0])
|
|
if (commitMessage.size() == 1) {
|
|
return
|
|
}
|
|
validateBody(commitMessage.subList(1, commitMessage.size()))
|
|
}
|
|
|
|
private void validateFirstLine(String firstLine) {
|
|
def matcher = COMMIT_FIRST_LINE.matcher(firstLine)
|
|
if (!matcher.find()) {
|
|
throw new InvalidUserDataException("Incorrect commit message format. See CONVENTIONAL_COMMITS.MD")
|
|
}
|
|
|
|
def commitType = matcher.group(1)
|
|
if (!commitTypes.contains(commitType)) {
|
|
throw new InvalidUserDataException("Unknown commit type '%s'. See CONVENTIONAL_COMMITS.MD".formatted(commitType))
|
|
}
|
|
|
|
def commitContext = matcher.group(2)
|
|
if (commitContext != null && !commitContexts.contains(commitContext)) {
|
|
throw new InvalidUserDataException("Unknown commit context '%s'. See CONVENTIONAL_COMMITS.MD".formatted(commitContext))
|
|
}
|
|
|
|
if (firstLine.length() > commitMaxLength) {
|
|
throw new InvalidUserDataException("Length of first line exceeds %d characters. See CONVENTIONAL_COMMITS.MD".formatted(commitMaxLength))
|
|
}
|
|
}
|
|
|
|
@SuppressWarnings('GrMethodMayBeStatic')
|
|
private void validateBody(List<String> commitMessage) {
|
|
println(commitMessage[0])
|
|
if (commitMessage[0] != "") {
|
|
throw new InvalidUserDataException("Use blank line before BODY. See CONVENTIONAL_COMMITS.MD")
|
|
}
|
|
|
|
def cc = commitMaxLength
|
|
if (commitMessage.subList(1, commitMessage.size()).any { it.length() > cc }) {
|
|
throw new InvalidUserDataException("Length of line in body part exceeds %d characters. See CONVENTIONAL_COMMITS.MD".formatted(commitMaxLength))
|
|
}
|
|
}
|
|
}
|