add: import code
портирован и слегка подправлен код из старого репозитория https://di9.ru/git/Voomra/Conventional-Commits
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
package ru.di9.gradle.commitlint
|
||||
|
||||
import org.gradle.api.provider.ListProperty
|
||||
import org.gradle.api.provider.Property
|
||||
|
||||
interface CommitLintExtension {
|
||||
|
||||
ListProperty<String> getTypes()
|
||||
|
||||
ListProperty<String> getContexts()
|
||||
|
||||
ListProperty<String> getExcludes()
|
||||
|
||||
Property<Integer> getMaxLengthLine()
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package ru.di9.gradle.commitlint
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
|
||||
@SuppressWarnings('unused')
|
||||
class CommitLintPlugin implements Plugin<Project> {
|
||||
|
||||
@Override
|
||||
void apply(Project project) {
|
||||
project.extensions.create("commitlint", CommitLintExtension)
|
||||
|
||||
project.tasks.register("commitlint", CommitLintTask, {
|
||||
group = "Verification"
|
||||
description = "commit lint"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
108
src/main/groovy/ru/di9/gradle/commitlint/CommitLintTask.groovy
Normal file
108
src/main/groovy/ru/di9/gradle/commitlint/CommitLintTask.groovy
Normal file
@@ -0,0 +1,108 @@
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user