mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IJI-3207 DevKit: remove intellij.devkit.git, which contained only pre-push handlers logic
GitOrigin-RevId: a9d06e72ef255c3eaef4e6f7d3c4c2f0680eb67f
This commit is contained in:
committed by
intellij-monorepo-bot
parent
703cb1fbc7
commit
6defd97d29
Generated
-1
@@ -389,7 +389,6 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/devkit/intellij.devkit.compose/intellij.devkit.compose.iml" filepath="$PROJECT_DIR$/plugins/devkit/intellij.devkit.compose/intellij.devkit.compose.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/devkit/devkit-core/intellij.devkit.core.iml" filepath="$PROJECT_DIR$/plugins/devkit/devkit-core/intellij.devkit.core.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/devkit/intellij.devkit.debugger/intellij.devkit.debugger.iml" filepath="$PROJECT_DIR$/plugins/devkit/intellij.devkit.debugger/intellij.devkit.debugger.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/devkit/intellij.devkit.git/intellij.devkit.git.iml" filepath="$PROJECT_DIR$/plugins/devkit/intellij.devkit.git/intellij.devkit.git.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/devkit/intellij.devkit.gradle/intellij.devkit.gradle.iml" filepath="$PROJECT_DIR$/plugins/devkit/intellij.devkit.gradle/intellij.devkit.gradle.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/devkit/intellij.devkit.i18n/intellij.devkit.i18n.iml" filepath="$PROJECT_DIR$/plugins/devkit/intellij.devkit.i18n/intellij.devkit.i18n.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/devkit/intellij.devkit.intelliLang/intellij.devkit.intelliLang.iml" filepath="$PROJECT_DIR$/plugins/devkit/intellij.devkit.intelliLang/intellij.devkit.intelliLang.iml" />
|
||||
|
||||
@@ -884,7 +884,6 @@ plugins/devkit/devkit-kotlin-tests
|
||||
plugins/devkit/devkit-tests
|
||||
plugins/devkit/intellij.devkit.compose
|
||||
plugins/devkit/intellij.devkit.debugger
|
||||
plugins/devkit/intellij.devkit.git
|
||||
plugins/devkit/intellij.devkit.gradle
|
||||
plugins/devkit/intellij.devkit.i18n
|
||||
plugins/devkit/intellij.devkit.intelliLang
|
||||
|
||||
@@ -57,7 +57,6 @@ jvm_library(
|
||||
"//plugins/devkit",
|
||||
"//plugins/devkit/devkit-core:core",
|
||||
"//plugins/devkit/intellij.devkit.debugger:debugger",
|
||||
"//plugins/devkit/intellij.devkit.git:git",
|
||||
"//plugins/devkit/intellij.devkit.gradle:gradle",
|
||||
"//plugins/devkit/intellij.devkit.i18n:i18n",
|
||||
"//plugins/devkit/intellij.devkit.intelliLang:intelliLang",
|
||||
@@ -81,7 +80,6 @@ jvm_library(
|
||||
"//plugins/devkit",
|
||||
"//plugins/devkit/devkit-core:core",
|
||||
"//plugins/devkit/intellij.devkit.debugger:debugger",
|
||||
"//plugins/devkit/intellij.devkit.git:git",
|
||||
"//plugins/devkit/intellij.devkit.gradle:gradle",
|
||||
"//plugins/devkit/intellij.devkit.i18n:i18n",
|
||||
"//plugins/devkit/intellij.devkit.intelliLang:intelliLang",
|
||||
|
||||
@@ -708,10 +708,6 @@
|
||||
<registryKey key="tmh.generate.line.numbers" defaultValue="true"
|
||||
description="Generate line numbers when instrumenting @RequiresEdt and similar annotations.
|
||||
This results in better stack traces when generated assertions throw exceptions, but might slow down the compilation."/>
|
||||
<registryKey key="kotlin.notebook.commit.message.validation.enabled" defaultValue="true"
|
||||
description="Enables commit messages validation for Kotlin Notebook plugin"/>
|
||||
<registryKey key="kotlin.build.tools.code.ownership.commit.message.enabled" defaultValue="true"
|
||||
description="Enables commit messages validation for Kotlin Build Tools code ownership"/>
|
||||
<codeInsight.declarativeInlayProvider
|
||||
providerId="devkit.threading"
|
||||
bundle="messages.DevKitBundle"
|
||||
@@ -724,13 +720,6 @@
|
||||
<registryKey key="devkit.inlay.threading" defaultValue="false"
|
||||
description="Experimental inlays for Threading Annotations"/>
|
||||
|
||||
<registryKey key="intellij.monorepo.commit.message.validation.enabled" defaultValue="true"
|
||||
description="Enables commit messages validation for IntelliJ Monorepo"/>
|
||||
<registryKey key="aia.commit.message.validation.enabled" defaultValue="true"
|
||||
description="Enables commit messages validation for AI Assistant project"/>
|
||||
<registryKey key="toolbox.commit.message.validation.enabled" defaultValue="true"
|
||||
description="Enables commit messages validation for Toolbox project"/>
|
||||
|
||||
<generatedSourcesFilter implementation="org.jetbrains.idea.devkit.contentReport.ContentReportGeneratedSourcesFilter"/>
|
||||
|
||||
<!-- INTERNAL -->
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
### auto-generated section `build intellij.devkit.git` start
|
||||
load("@rules_jvm//:jvm.bzl", "jvm_library", "jvm_provided_library", "resourcegroup")
|
||||
|
||||
resourcegroup(
|
||||
name = "git_resources",
|
||||
srcs = glob(["resources/**/*"]),
|
||||
strip_prefix = "resources"
|
||||
)
|
||||
|
||||
jvm_provided_library(
|
||||
name = "platform_vcs-api_vcs-core_provided",
|
||||
lib = "//platform/vcs-api/vcs-api-core:vcs-core"
|
||||
)
|
||||
|
||||
jvm_provided_library(
|
||||
name = "platform_vcs-log_vcs-log_provided",
|
||||
lib = "//platform/vcs-log/api:vcs-log"
|
||||
)
|
||||
|
||||
jvm_provided_library(
|
||||
name = "platform_vcs-dvcs-impl_provided",
|
||||
lib = "//platform/dvcs-impl:vcs-dvcs-impl"
|
||||
)
|
||||
|
||||
jvm_provided_library(
|
||||
name = "plugins_vcs-git_provided",
|
||||
lib = "//plugins/git4idea:vcs-git"
|
||||
)
|
||||
|
||||
jvm_library(
|
||||
name = "git",
|
||||
module_name = "intellij.devkit.git",
|
||||
visibility = ["//visibility:public"],
|
||||
srcs = glob(["src/**/*.kt", "src/**/*.java", "src/**/*.form"], allow_empty = True),
|
||||
resources = [":git_resources"],
|
||||
deps = [
|
||||
"@lib//:kotlin-stdlib",
|
||||
"//platform/util-ex",
|
||||
"//platform/core-api:core",
|
||||
"//platform/projectModel-api:projectModel",
|
||||
"//platform/util",
|
||||
"//platform/ide-core",
|
||||
"//plugins/devkit/devkit-core:core",
|
||||
"//platform/vcs-api/shared",
|
||||
"//platform/vcs-log/impl",
|
||||
"//platform/platform-api:ide",
|
||||
":platform_vcs-api_vcs-core_provided",
|
||||
":platform_vcs-log_vcs-log_provided",
|
||||
":platform_vcs-dvcs-impl_provided",
|
||||
":plugins_vcs-git_provided",
|
||||
]
|
||||
)
|
||||
|
||||
jvm_provided_library(
|
||||
name = "platform_vcs-api_vcs-core_test_lib_provided",
|
||||
lib = "//platform/vcs-api/vcs-api-core:vcs-core_test_lib"
|
||||
)
|
||||
|
||||
jvm_provided_library(
|
||||
name = "platform_vcs-dvcs-impl_test_lib_provided",
|
||||
lib = "//platform/dvcs-impl:vcs-dvcs-impl_test_lib"
|
||||
)
|
||||
|
||||
jvm_provided_library(
|
||||
name = "plugins_vcs-git_test_lib_provided",
|
||||
lib = "//plugins/git4idea:vcs-git_test_lib"
|
||||
)
|
||||
|
||||
jvm_library(
|
||||
name = "git_test_lib",
|
||||
visibility = ["//visibility:public"],
|
||||
srcs = glob(["test/**/*.kt", "test/**/*.java", "test/**/*.form"], allow_empty = True),
|
||||
associates = [":git"],
|
||||
deps = [
|
||||
"@lib//:kotlin-stdlib",
|
||||
"//platform/util-ex",
|
||||
"//platform/core-api:core",
|
||||
"//platform/projectModel-api:projectModel",
|
||||
"//platform/util",
|
||||
"//platform/ide-core",
|
||||
"//plugins/devkit/devkit-core:core",
|
||||
"@lib//:junit4",
|
||||
"//platform/testFramework",
|
||||
"//platform/testFramework:testFramework_test_lib",
|
||||
"//platform/vcs-api/shared",
|
||||
"//platform/vcs-log/impl",
|
||||
"//platform/vcs-log/impl:impl_test_lib",
|
||||
"//platform/platform-api:ide",
|
||||
":platform_vcs-api_vcs-core_provided",
|
||||
":platform_vcs-log_vcs-log_provided",
|
||||
":platform_vcs-dvcs-impl_provided",
|
||||
":plugins_vcs-git_provided",
|
||||
":platform_vcs-api_vcs-core_test_lib_provided",
|
||||
":platform_vcs-dvcs-impl_test_lib_provided",
|
||||
":plugins_vcs-git_test_lib_provided",
|
||||
]
|
||||
)
|
||||
### auto-generated section `build intellij.devkit.git` end
|
||||
|
||||
### auto-generated section `test intellij.devkit.git` start
|
||||
load("@community//build:tests-options.bzl", "jps_test")
|
||||
|
||||
jps_test(
|
||||
name = "git_test",
|
||||
runtime_deps = [":git_test_lib"]
|
||||
)
|
||||
### auto-generated section `test intellij.devkit.git` end
|
||||
@@ -1,29 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="org.jetbrains.idea.devkit.commit" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" packagePrefix="org.jetbrains.idea.devkit.commit" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="kotlin-stdlib" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.util.ex" />
|
||||
<orderEntry type="module" module-name="intellij.platform.core" />
|
||||
<orderEntry type="module" module-name="intellij.platform.projectModel" />
|
||||
<orderEntry type="module" module-name="intellij.platform.util" />
|
||||
<orderEntry type="module" module-name="intellij.platform.ide.core" />
|
||||
<orderEntry type="module" module-name="intellij.platform.vcs.core" scope="PROVIDED" />
|
||||
<orderEntry type="module" module-name="intellij.platform.vcs.log" scope="PROVIDED" />
|
||||
<orderEntry type="module" module-name="intellij.platform.vcs.dvcs.impl" scope="PROVIDED" />
|
||||
<orderEntry type="module" module-name="intellij.vcs.git" scope="PROVIDED" />
|
||||
<orderEntry type="module" module-name="intellij.devkit.core" />
|
||||
<orderEntry type="library" scope="TEST" name="JUnit4" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.testFramework" scope="TEST" />
|
||||
<orderEntry type="module" module-name="intellij.platform.vcs.shared" />
|
||||
<orderEntry type="module" module-name="intellij.platform.vcs.log.impl" />
|
||||
<orderEntry type="module" module-name="intellij.platform.ide" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -1,13 +0,0 @@
|
||||
<idea-plugin package="org.jetbrains.idea.devkit.commit">
|
||||
<dependencies>
|
||||
<module name="intellij.devkit.core"/>
|
||||
<plugin id="Git4Idea"/>
|
||||
<module name="intellij.platform.vcs.log.impl"/>
|
||||
</dependencies>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<prePushHandler implementation="org.jetbrains.idea.devkit.commit.KotlinBuildToolsPrePushHandler"/>
|
||||
<prePushHandler implementation="org.jetbrains.idea.devkit.commit.KotlinNotebookPluginPrePushHandler"/>
|
||||
<prePushHandler implementation="org.jetbrains.idea.devkit.commit.IntelliJMonorepoPrePushHandler"/>
|
||||
<prePushHandler implementation="org.jetbrains.idea.devkit.commit.ToolboxPrePushHandler"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -1,38 +0,0 @@
|
||||
push.commit.message.lacks.issue.reference.body=\
|
||||
<html>Commits listed below change the Kotlin IDE plugin sources. According to the rules of the plugin team, \
|
||||
<a href=https://github.com/JetBrains/intellij-community/blob/master/plugins/kotlin/README.md#2-commits-requirements>all meaningful commits</a> \
|
||||
should reference a {0} issue in their message. Do you still want to push as is? \
|
||||
<pre>{1}</pre> \
|
||||
</html>
|
||||
push.commit.message.lacks.issue.reference.title=Message Lacks YouTrack Issue Reference
|
||||
push.commit.message.lacks.issue.reference.commit=Push As Is
|
||||
push.commit.message.lacks.issue.reference.edit=Edit Message(s)
|
||||
|
||||
push.commit.kotlin.notebook.handler.name=Kotlin Notebook Plugin Push Handler
|
||||
|
||||
push.commit.intellij.platform.handler.name=IntelliJ Monorepo Push Handler
|
||||
push.commit.intellij.platform.handler.title=Please Mention a YouTrack Issue in Commit Messages
|
||||
push.commit.intellij.platform.message.lacks.issue.reference.body=\
|
||||
<html>Commits listed below change the JetBrains IDEs product's code. \
|
||||
Please follow a commit message format (see README.md in mono repository root) and reference a YouTrack issue in commit messages which change modifies product's distribution.<br/><br/> \
|
||||
<a href="https://youtrack.jetbrains.com/newIssue">Create</a> an issue or use any IDE-related YT ticket ID.<br/><br/> \
|
||||
</html>
|
||||
|
||||
push.commit.kotlin.build.tools.handler.name=Kotlin Build Tools Code Ownership Push Handler
|
||||
push.commit.kotlin.build.tools.review.title=Kotlin Build Tools Code Ownership Warning
|
||||
push.commit.kotlin.build.tools.message.lacks.issue.reference.body=\
|
||||
<html>Commits listed below change the Kotlin Build Tools code.<br/><br/>\
|
||||
According to the rules of the Kotlin Build Tools team, \
|
||||
all commits to their codebase have to pass mandatory pre-review.\
|
||||
<pre>{0}</pre> \
|
||||
</html>
|
||||
|
||||
toolbox.commit.handler.name=Toolbox Push Handler
|
||||
toolbox.push.commit.message.lacks.issue.reference.title=Please Mention a YouTrack Issue in Commit Messages
|
||||
toolbox.push.commit.message.lacks.issue.reference.body=\
|
||||
<html>Commits listed below change the Toolbox or Station code. <br/> \
|
||||
Please reference a <a href="https://youtrack.jetbrains.com/newIssue?project=TBX">TBX</a> issue in the commit messages. <br/> \
|
||||
Issues from other projects, like <a href="https://youtrack.jetbrains.com/newIssue?project=IJPL">IJPL</a> or <a href="https://youtrack.jetbrains.com/newIssue?project=IDES">IDES</a> could be used as well. <br/> \
|
||||
Do you still want to push as is? <br/>\
|
||||
<br><code>{0}</code> \
|
||||
</html>
|
||||
@@ -1,78 +0,0 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.idea.devkit.commit
|
||||
|
||||
import com.intellij.dvcs.push.PrePushHandler
|
||||
import com.intellij.dvcs.push.PushInfo
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.progress.ProgressIndicator
|
||||
import com.intellij.openapi.project.IntelliJProjectUtil
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import com.intellij.openapi.vcs.changes.ContentRevision
|
||||
import com.intellij.vcs.log.VcsFullCommitDetails
|
||||
import git4idea.config.GitSharedSettings
|
||||
import java.nio.file.Path
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
import kotlin.io.path.extension
|
||||
import kotlin.io.path.invariantSeparatorsPathString
|
||||
|
||||
internal abstract class AbstractIntelliJProjectPrePushHandler : PrePushHandler {
|
||||
protected abstract fun isAvailable(): Boolean
|
||||
|
||||
private fun handlerIsApplicable(project: Project): Boolean =
|
||||
isAvailable() && IntelliJProjectUtil.isIntelliJPlatformProject(project)
|
||||
|
||||
final override fun handle(project: Project, pushDetails: List<PushInfo>, indicator: ProgressIndicator): PrePushHandler.Result {
|
||||
if (!handlerIsApplicable(project)) {
|
||||
return PrePushHandler.Result.OK
|
||||
}
|
||||
|
||||
if (pushDetails.any {
|
||||
isTargetBranchProtected(project, it)
|
||||
&& validate(project, it, indicator) == PushInfoValidationResult.INVALID
|
||||
}) {
|
||||
return PrePushHandler.Result.ABORT_AND_CLOSE
|
||||
}
|
||||
|
||||
return PrePushHandler.Result.OK
|
||||
}
|
||||
|
||||
protected open fun isTargetBranchProtected(project: Project, pushInfo: PushInfo): Boolean =
|
||||
GitSharedSettings.getInstance(project).isBranchProtected(pushInfo.pushSpec.target.presentation)
|
||||
|
||||
protected abstract fun validate(project: Project, info: PushInfo, indicator: ProgressIndicator): PushInfoValidationResult
|
||||
|
||||
protected enum class PushInfoValidationResult {
|
||||
VALID, INVALID, SKIP
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
protected val ContentRevision.path: Path?
|
||||
get() = file.takeIf { !it.isNonLocal }?.ioFile?.toPath() // TODO: handle non-local?
|
||||
|
||||
private val fileExtensionsNotToTrack = setOf("iml", "md")
|
||||
|
||||
@JvmStatic
|
||||
protected fun Sequence<Path>.anyIn(paths: List<String>, pathsToIgnore: List<String>): Boolean =
|
||||
any { path ->
|
||||
val siPath = path.invariantSeparatorsPathString
|
||||
path.extension !in fileExtensionsNotToTrack
|
||||
&& paths.any { siPath.contains(it) }
|
||||
&& pathsToIgnore.none { siPath.contains(it) }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
protected fun List<VcsFullCommitDetails>.toHtml(): @NlsSafe String =
|
||||
joinToString("<br/>") { commit ->
|
||||
"${commit.id.toShortString()}: ${commit.subject}"
|
||||
}
|
||||
|
||||
internal fun <T> invokeAndWait(modalityState: ModalityState, computable: () -> T): T {
|
||||
val ref = AtomicReference<T>()
|
||||
ApplicationManager.getApplication().invokeAndWait({ ref.set(computable.invoke()) }, modalityState)
|
||||
return ref.get()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.idea.devkit.commit;
|
||||
|
||||
import com.intellij.DynamicBundle;
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
final class DevKitGitBundle {
|
||||
|
||||
private static final @NonNls String BUNDLE_FQN = "messages.DevKitGitBundle";
|
||||
private static final DynamicBundle BUNDLE = new DynamicBundle(DevKitGitBundle.class, BUNDLE_FQN);
|
||||
|
||||
private DevKitGitBundle() {
|
||||
}
|
||||
|
||||
public static @Nls @NotNull String message(
|
||||
@PropertyKey(resourceBundle = BUNDLE_FQN) @NotNull String key,
|
||||
@Nullable Object @NotNull ... params
|
||||
) {
|
||||
return BUNDLE.getMessage(key, params);
|
||||
}
|
||||
|
||||
public static @NotNull Supplier<@Nls @NotNull String> messagePointer(
|
||||
@PropertyKey(resourceBundle = BUNDLE_FQN) @NotNull String key,
|
||||
@Nullable Object @NotNull ... params
|
||||
) {
|
||||
return BUNDLE.getLazyMessage(key, params);
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.idea.devkit.commit
|
||||
|
||||
import com.intellij.dvcs.push.PushInfo
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.progress.ProgressIndicator
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.MessageDialogBuilder
|
||||
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread
|
||||
import com.intellij.vcs.log.VcsFullCommitDetails
|
||||
import com.intellij.vcs.log.impl.VcsProjectLog
|
||||
import org.jetbrains.annotations.VisibleForTesting
|
||||
import java.nio.file.Path
|
||||
|
||||
internal abstract class IssueIDPrePushHandler : AbstractIntelliJProjectPrePushHandler() {
|
||||
protected open val acceptableProjects = listOf(
|
||||
"KTIJ", "KTNB", "KT", "IDEA", "IJPL"
|
||||
)
|
||||
protected abstract val commitMessageRegex: Regex
|
||||
protected open val ignorePattern: Regex = Regex("(?!.*)")
|
||||
|
||||
protected open val paths: List<String> = listOf()
|
||||
protected open val pathsToIgnore: List<String> = listOf("/test/", "/testData/")
|
||||
protected open val validateCommitsOnlyFromCurrentUser: Boolean = false
|
||||
|
||||
final override fun validate(project: Project, info: PushInfo, indicator: ProgressIndicator): PushInfoValidationResult {
|
||||
val commitsToWarnAbout = info.commits.filterNot { isCommitValid(project, it) }
|
||||
if (commitsToWarnAbout.isEmpty()) {
|
||||
return PushInfoValidationResult.VALID
|
||||
}
|
||||
|
||||
val skip = handleCommitsValidationFailure(project, info, commitsToWarnAbout, indicator.modalityState)
|
||||
if (skip) return PushInfoValidationResult.SKIP
|
||||
|
||||
return PushInfoValidationResult.INVALID
|
||||
}
|
||||
|
||||
private fun isCommitValid(project: Project, commit: VcsFullCommitDetails): Boolean {
|
||||
if (validateCommitsOnlyFromCurrentUser) {
|
||||
val currentUsers = VcsProjectLog.getInstance(project).dataManager?.userNameResolver?.resolveCurrentUser(commit.root)
|
||||
val committer = commit.committer
|
||||
// allow commits from other people:
|
||||
if (currentUsers != null && committer.email !in currentUsers.map { it.email }) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
val commitPaths = commit.changes.asSequence().flatMap { change ->
|
||||
sequenceOf(change.beforeRevision?.path, change.afterRevision?.path).filterNotNull()
|
||||
}
|
||||
if (!containSources(commitPaths)) {
|
||||
return true
|
||||
}
|
||||
|
||||
return isCommitMessageCorrect(commit.fullMessage)
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
fun containSources(sourcePaths: Sequence<Path>): Boolean = sourcePaths.anyIn(paths, pathsToIgnore)
|
||||
|
||||
/**
|
||||
* Notify the user about commits that don't pass validation.
|
||||
* Commits in [commitsToWarnAbout] are ordered from oldest to newest.
|
||||
*
|
||||
* @return `true` if user decided to skip validation, `false` otherwise.
|
||||
*/
|
||||
@RequiresBackgroundThread
|
||||
protected open fun handleCommitsValidationFailure(
|
||||
project: Project,
|
||||
info: PushInfo,
|
||||
commitsToWarnAbout: List<VcsFullCommitDetails>,
|
||||
modalityState: ModalityState,
|
||||
): Boolean {
|
||||
val lastAcceptableProjectIndex = acceptableProjects.lastIndex
|
||||
val acceptableProjectIssueLinks = acceptableProjects.mapIndexed { index, projectId ->
|
||||
val link = getProjectIssueLink(projectId)
|
||||
val suffix = when(index) {
|
||||
lastAcceptableProjectIndex -> ""
|
||||
lastAcceptableProjectIndex - 1 -> " or "
|
||||
else -> ", "
|
||||
}
|
||||
link + suffix
|
||||
}.joinToString("")
|
||||
|
||||
val commitsInfo = commitsToWarnAbout.toHtml()
|
||||
|
||||
val commitAsIs = invokeAndWait(modalityState) {
|
||||
@Suppress("DialogTitleCapitalization")
|
||||
MessageDialogBuilder.yesNo(
|
||||
DevKitGitBundle.message("push.commit.message.lacks.issue.reference.title"),
|
||||
DevKitGitBundle.message(
|
||||
"push.commit.message.lacks.issue.reference.body",
|
||||
acceptableProjectIssueLinks,
|
||||
commitsInfo
|
||||
)
|
||||
)
|
||||
.yesText(DevKitGitBundle.message("push.commit.message.lacks.issue.reference.commit"))
|
||||
.noText(DevKitGitBundle.message("push.commit.message.lacks.issue.reference.edit"))
|
||||
.asWarning()
|
||||
.ask(project = null)
|
||||
}
|
||||
|
||||
return commitAsIs
|
||||
}
|
||||
|
||||
fun isCommitMessageCorrect(message: String): Boolean {
|
||||
if (message == "Rename .java to .kt") {
|
||||
return true
|
||||
}
|
||||
return message.matches(commitMessageRegex) || message.matches(ignorePattern)
|
||||
}
|
||||
|
||||
protected fun buildRegexFromAcceptableProjects(): Regex {
|
||||
@Suppress("RegExpUnnecessaryNonCapturingGroup")
|
||||
return Regex(
|
||||
".*(?:${acceptableProjects.joinToString("|")})-\\d+.*",
|
||||
RegexOption.DOT_MATCHES_ALL /* line breaks matter */
|
||||
)
|
||||
}
|
||||
|
||||
private fun getProjectIssueLink(projectId: String) =
|
||||
"<a href=\"https://youtrack.jetbrains.com/newIssue?project=$projectId\">$projectId</a>"
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.idea.devkit.commit
|
||||
|
||||
import com.intellij.dvcs.push.PushInfo
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.diagnostic.thisLogger
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.DialogWrapper
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.ui.components.JBScrollPane
|
||||
import com.intellij.vcs.log.VcsFullCommitDetails
|
||||
import git4idea.rebase.GitInteractiveRebaseService
|
||||
import git4idea.repo.GitRepository
|
||||
import org.jetbrains.annotations.Nls
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Dimension
|
||||
import javax.swing.Action
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JEditorPane
|
||||
import javax.swing.JPanel
|
||||
|
||||
internal class IntelliJMonorepoPrePushHandler : IssueIDPrePushHandler() {
|
||||
private val protectedBranches = listOf("ij-ai/", "ij-aia/", "ide-next/")
|
||||
|
||||
override val paths: List<String> = listOf(
|
||||
"/community/platform/",
|
||||
"remote-dev", // ij platform
|
||||
"plugins/kotlin/", // kotlin plugin
|
||||
"plugins/llm/", "plugins/llm-installer/", "plugins/full-line/", // aia plugin
|
||||
)
|
||||
override val pathsToIgnore: List<String> = super.pathsToIgnore.toMutableList()
|
||||
.apply { add("/fleet/plugins/kotlin/") }
|
||||
.apply { add("/plugins/kotlin/jupyter/") }
|
||||
|
||||
override val commitMessageRegex = Regex("""(?:^|.*[^-A-Z0-9])[A-Z]+-\d+.*""", RegexOption.DOT_MATCHES_ALL)
|
||||
override val ignorePattern = Regex(
|
||||
pattern = """^(?:\[.+] ?)?\[?(?:tests?|clean ?up|docs?|typo|refactor(?:ing)?|format|style|testFramework|test framework)]?.*\s.*[A-Z0-9](?:.|\n)*|(?:.*[^a-z])?WIP(?:[^a-z](?:.|\n)*)?""",
|
||||
option = RegexOption.IGNORE_CASE
|
||||
)
|
||||
override val validateCommitsOnlyFromCurrentUser: Boolean = true
|
||||
|
||||
override fun isTargetBranchProtected(project: Project, pushInfo: PushInfo): Boolean {
|
||||
return super.isTargetBranchProtected(project, pushInfo) || protectedBranches.any { pushInfo.pushSpec.target.presentation.startsWith(it) }
|
||||
}
|
||||
|
||||
override fun isAvailable(): Boolean = Registry.`is`("intellij.monorepo.commit.message.validation.enabled", true)
|
||||
override fun getPresentableName(): @Nls String = DevKitGitBundle.message("push.commit.intellij.platform.handler.name")
|
||||
|
||||
override fun handleCommitsValidationFailure(
|
||||
project: Project,
|
||||
info: PushInfo,
|
||||
commitsToWarnAbout: List<VcsFullCommitDetails>,
|
||||
modalityState: ModalityState,
|
||||
): Boolean {
|
||||
val commitsInfo = commitsToWarnAbout.toHtml()
|
||||
|
||||
val result = invokeAndWait(modalityState) {
|
||||
val dialog = CommitValidationDialog(project, commitsInfo)
|
||||
dialog.show()
|
||||
dialog.exitCode
|
||||
}
|
||||
|
||||
if (result == CommitValidationDialog.EDIT_EXIT_CODE) {
|
||||
val repository = info.repository as? GitRepository ?: run {
|
||||
thisLogger().error("Unexpected repository type: ${info.repository}")
|
||||
return false
|
||||
}
|
||||
project.service<GitInteractiveRebaseService>().launchRebase(repository, commitsToWarnAbout.first())
|
||||
}
|
||||
|
||||
return result == DialogWrapper.OK_EXIT_CODE
|
||||
}
|
||||
}
|
||||
|
||||
private class CommitValidationDialog(
|
||||
project: Project,
|
||||
private val commitsInfo: String
|
||||
) : DialogWrapper(project) {
|
||||
|
||||
companion object {
|
||||
const val EDIT_EXIT_CODE = NEXT_USER_EXIT_CODE + 1
|
||||
}
|
||||
|
||||
private val editAction = object : DialogWrapperAction(DevKitGitBundle.message("push.commit.message.lacks.issue.reference.edit")) {
|
||||
override fun doAction(e: java.awt.event.ActionEvent) {
|
||||
close(EDIT_EXIT_CODE)
|
||||
}
|
||||
}
|
||||
|
||||
private val commitAction = object : DialogWrapperAction(DevKitGitBundle.message("push.commit.message.lacks.issue.reference.commit")) {
|
||||
override fun doAction(e: java.awt.event.ActionEvent) {
|
||||
close(OK_EXIT_CODE)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
title = DevKitGitBundle.message("push.commit.intellij.platform.handler.title")
|
||||
isResizable = true
|
||||
init()
|
||||
rootPane.defaultButton = getButton(editAction)
|
||||
}
|
||||
|
||||
override fun createCenterPanel(): JComponent {
|
||||
val panel = JPanel(BorderLayout())
|
||||
val explanationPane = JEditorPane("text/html", DevKitGitBundle.message("push.commit.intellij.platform.message.lacks.issue.reference.body", commitsInfo)).apply {
|
||||
isEditable = false
|
||||
background = panel.background
|
||||
putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, true)
|
||||
border = null
|
||||
}
|
||||
@Suppress("HardCodedStringLiteral")
|
||||
val commitInfoPane = JEditorPane("text/html", "<pre>${commitsInfo.replace("\n", "<br/>")}</pre>").apply {
|
||||
isEditable = false
|
||||
background = panel.background
|
||||
}
|
||||
val scrollPane = JBScrollPane(commitInfoPane).apply {
|
||||
minimumSize = Dimension(400, 150)
|
||||
preferredSize = Dimension(600, 300)
|
||||
verticalScrollBarPolicy = JBScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED
|
||||
horizontalScrollBarPolicy = JBScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED
|
||||
border = null
|
||||
}
|
||||
panel.add(explanationPane, BorderLayout.NORTH)
|
||||
panel.add(scrollPane, BorderLayout.CENTER)
|
||||
return panel
|
||||
}
|
||||
|
||||
override fun createActions(): Array<Action> {
|
||||
return arrayOf(
|
||||
commitAction,
|
||||
editAction,
|
||||
cancelAction
|
||||
)
|
||||
}
|
||||
|
||||
override fun getDimensionServiceKey(): String {
|
||||
return "IntelliJPlatformCommitValidationDialog"
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.idea.devkit.commit
|
||||
|
||||
import com.intellij.dvcs.push.PushInfo
|
||||
import com.intellij.openapi.progress.ProgressIndicator
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.MessageDialogBuilder
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import org.jetbrains.annotations.Nls
|
||||
import java.nio.file.Path
|
||||
|
||||
internal class KotlinNotebookPluginPrePushHandler : IssueIDPrePushHandler() {
|
||||
override val paths: List<String> = listOf("plugins/kotlin/jupyter/")
|
||||
override val acceptableProjects: List<String> = super.acceptableProjects + listOf(
|
||||
"PY"
|
||||
)
|
||||
override val commitMessageRegex = buildRegexFromAcceptableProjects()
|
||||
|
||||
override fun isAvailable(): Boolean = Registry.`is`("kotlin.notebook.commit.message.validation.enabled", true)
|
||||
override fun getPresentableName(): String = DevKitGitBundle.message("push.commit.kotlin.notebook.handler.name")
|
||||
}
|
||||
|
||||
|
||||
private val KOTLIN_BUILD_TOOLS_PATHS_TO_IGNORE: List<String> =
|
||||
listOf("community/plugins/kotlin/gradle/gradle-java/k1/test/org/jetbrains/kotlin/idea/scripting/")
|
||||
|
||||
// To be in sync with https://jetbrains.team/p/ij/repositories/ultimate-teamcity-config/files/master/.teamcity/src/idea/cherryPickRobot/branchReviewRules/BranchReviewRules.kt
|
||||
// see approval(ReviewerGroups.kotlinBuildToolsTeam)
|
||||
private val KOTLIN_BUILD_TOOLS_PATHS: List<String> =
|
||||
listOf(
|
||||
"community/plugins/kotlin/base/facet/",
|
||||
"community/plugins/kotlin/base/jps/",
|
||||
"community/plugins/kotlin/base/external-build-system/",
|
||||
"community/plugins/kotlin/gradle/gradle/",
|
||||
"community/plugins/kotlin/gradle/gradle-tooling/",
|
||||
"community/plugins/kotlin/gradle/gradle-java/",
|
||||
"community/plugins/kotlin/gradle/multiplatform-tests/",
|
||||
"community/plugins/kotlin/gradle/multiplatform-tests-k2/",
|
||||
"community/plugins/kotlin/jps/",
|
||||
"community/plugins/kotlin/maven/"
|
||||
)
|
||||
|
||||
internal class KotlinBuildToolsPrePushHandler : AbstractIntelliJProjectPrePushHandler() {
|
||||
override fun isAvailable(): Boolean =
|
||||
Registry.`is`("kotlin.build.tools.code.ownership.commit.message.enabled", true)
|
||||
|
||||
override fun getPresentableName(): @Nls(capitalization = Nls.Capitalization.Title) String =
|
||||
DevKitGitBundle.message("push.commit.kotlin.build.tools.handler.name")
|
||||
|
||||
override fun isTargetBranchProtected(project: Project, pushInfo: PushInfo): Boolean {
|
||||
return super.isTargetBranchProtected(project, pushInfo) || pushInfo.pushSpec.target.presentation == "kt-master"
|
||||
}
|
||||
|
||||
override fun validate(project: Project, info: PushInfo, indicator: ProgressIndicator): PushInfoValidationResult {
|
||||
val matchingCommits = info.commits.filter { commit ->
|
||||
commit.changes.asSequence()
|
||||
.mapNotNull { it.virtualFile }
|
||||
.map { Path.of(it.path) }
|
||||
.anyIn(KOTLIN_BUILD_TOOLS_PATHS, KOTLIN_BUILD_TOOLS_PATHS_TO_IGNORE)
|
||||
}
|
||||
|
||||
if (matchingCommits.isNotEmpty()) {
|
||||
val commitsInfo = matchingCommits.toHtml()
|
||||
invokeAndWait(indicator.modalityState) {
|
||||
MessageDialogBuilder.okCancel(
|
||||
DevKitGitBundle.message("push.commit.kotlin.build.tools.review.title"),
|
||||
DevKitGitBundle.message("push.commit.kotlin.build.tools.message.lacks.issue.reference.body", commitsInfo)
|
||||
)
|
||||
.asWarning()
|
||||
.ask(project = null)
|
||||
}
|
||||
}
|
||||
|
||||
return PushInfoValidationResult.VALID
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.idea.devkit.commit
|
||||
|
||||
import com.intellij.dvcs.push.PushInfo
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.MessageDialogBuilder
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.vcs.log.VcsFullCommitDetails
|
||||
|
||||
internal class ToolboxPrePushHandler : IssueIDPrePushHandler() {
|
||||
override val paths = listOf("toolbox/", "station/")
|
||||
|
||||
override val acceptableProjects: List<String> = super.acceptableProjects + listOf(
|
||||
"TBX", "IDES"
|
||||
)
|
||||
|
||||
private val acceptableGroup = listOf(
|
||||
"docs", "doc",
|
||||
"cleanup", "typo",
|
||||
"refactoring", "refactor", "format",
|
||||
"tests", "test"
|
||||
)
|
||||
|
||||
private val groupPattern = Regex("""\b(${acceptableGroup.joinToString("|")})\b.*""", RegexOption.IGNORE_CASE)
|
||||
|
||||
override val commitMessageRegex: Regex = Regex(
|
||||
"(${buildRegexFromAcceptableProjects().pattern})|(${groupPattern.pattern})",
|
||||
setOf(RegexOption.DOT_MATCHES_ALL, RegexOption.IGNORE_CASE)
|
||||
)
|
||||
override fun isAvailable(): Boolean = Registry.`is`("toolbox.commit.message.validation.enabled", true)
|
||||
|
||||
override fun getPresentableName(): String = DevKitGitBundle.message("toolbox.commit.handler.name")
|
||||
|
||||
override fun handleCommitsValidationFailure(project: Project, info: PushInfo, commitsToWarnAbout: List<VcsFullCommitDetails>, modalityState: ModalityState): Boolean {
|
||||
val commitsInfo = commitsToWarnAbout.toHtml()
|
||||
|
||||
val commitAsIs = invokeAndWait(modalityState) {
|
||||
@Suppress("DialogTitleCapitalization")
|
||||
MessageDialogBuilder.yesNo(
|
||||
DevKitGitBundle.message("toolbox.push.commit.message.lacks.issue.reference.title"),
|
||||
DevKitGitBundle.message("toolbox.push.commit.message.lacks.issue.reference.body", commitsInfo)
|
||||
)
|
||||
.yesText(DevKitGitBundle.message("push.commit.message.lacks.issue.reference.commit"))
|
||||
.noText(DevKitGitBundle.message("push.commit.message.lacks.issue.reference.edit"))
|
||||
.asWarning()
|
||||
.ask(project)
|
||||
}
|
||||
|
||||
return commitAsIs
|
||||
}
|
||||
}
|
||||
@@ -1,387 +0,0 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.idea.devkit.commit
|
||||
|
||||
import com.intellij.openapi.application.PathManager
|
||||
import org.junit.Test
|
||||
import org.junit.experimental.runners.Enclosed
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.Parameterized
|
||||
import org.junit.runners.Parameterized.Parameter
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import kotlin.io.path.div
|
||||
import kotlin.io.path.exists
|
||||
import kotlin.io.path.readText
|
||||
|
||||
@RunWith(Enclosed::class)
|
||||
class IntelliJMonorepoPrePushHandlerTest {
|
||||
|
||||
@RunWith(Parameterized::class)
|
||||
class FilesBelongToPlatform {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
fun provideTestParameters(): Iterable<List<String>> {
|
||||
return listOf(
|
||||
listOf("${COMMUNITY_PLATFORM}/File.kt"),
|
||||
listOf(
|
||||
"${COMMUNITY_PLATFORM}/File.kt",
|
||||
"root.txt",
|
||||
),
|
||||
listOf(
|
||||
"${COMMUNITY_PLATFORM}/File.kt",
|
||||
"${COMMUNITY}/plugins/stuff.xml",
|
||||
"not-important-dir-A/whatever",
|
||||
"not-important-dir-B/whatever"
|
||||
),
|
||||
listOf("unrelated/$COMMUNITY_PLATFORM/File.kt"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Parameter
|
||||
lateinit var files: List<String>
|
||||
|
||||
@Test
|
||||
fun testThatChecksForFileSet() {
|
||||
val filesSet = files.asSequence().map { pathAt(it) }
|
||||
assert(prePushHandler.containSources(filesSet)) {
|
||||
"The following set of files doesn't trigger the check: $filesSet"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@RunWith(Parameterized::class)
|
||||
class FilesDoNotBelongToPlatform {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
fun provideTestParameters(): Iterable<List<String>> {
|
||||
return listOf(
|
||||
listOf("${COMMUNITY_PLATFORM}/README.md"),
|
||||
listOf("${COMMUNITY_PLATFORM}/sub/sub.iml"),
|
||||
|
||||
listOf("${COMMUNITY}/File.kt"),
|
||||
listOf("${COMMUNITY}/README.md"),
|
||||
listOf("${COMMUNITY}/sub/sub.iml"),
|
||||
listOf(
|
||||
"${COMMUNITY}/plugins/stuff.xml",
|
||||
"not-important-dir-A/whatever",
|
||||
"not-important-dir-B/whatever",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Parameter
|
||||
lateinit var files: List<String>
|
||||
|
||||
@Test
|
||||
fun testThatIgnoresFileSet() {
|
||||
val filesSet = files.asSequence().map { pathAt(it) }
|
||||
assert(!prePushHandler.containSources(filesSet)) {
|
||||
"The following set of files triggered the check: $filesSet"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(Parameterized::class)
|
||||
class ValidCommitMessages {
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
fun provideTestParameters(): Iterable<String> {
|
||||
return listOf(
|
||||
"IJPL-1", "A-1",
|
||||
"IJPL-123", "(IJPL-123)", "[IJPL-123]", "{IJPL-123}", "'IJPL-123'", "`IJPL-123`", "\"IJPL-123\"",
|
||||
"IDEA-123", "(IDEA-123)", "[IDEA-123]", "{IDEA-123}", "'IDEA-123'", "`IDEA-123`", "\"IDEA-123\"",
|
||||
"IJPL-42",
|
||||
"KTIJ-123 ", " KTIJ-123", " KTIJ-123 ", "IDEA-123 ",
|
||||
" IDEA-123", " IDEA-123 ",
|
||||
"IJPL-123 header",
|
||||
"Header IJPL-123",
|
||||
"[sub system 123] docs: fix typo",
|
||||
"Header IJPL-123 header",
|
||||
"IJPL-123 header",
|
||||
"Header IJPL-123",
|
||||
"Header IJPL-123 header",
|
||||
"""
|
||||
Header IJPL-123 header
|
||||
|
||||
Body-line-1
|
||||
Body-line-N
|
||||
""".trimIndent(),
|
||||
"""
|
||||
Header IJPL-123 header
|
||||
|
||||
Body-line-1
|
||||
Body-line-N
|
||||
""".trimIndent(),
|
||||
"""
|
||||
Header IJPL-123 header
|
||||
|
||||
Body-line-1
|
||||
Body-line-N
|
||||
|
||||
^IJPL-123 fixed
|
||||
""".trimIndent(),
|
||||
"""
|
||||
Header IJPL-123 header
|
||||
|
||||
Body-line-1
|
||||
Body-line-N
|
||||
|
||||
^IDEA-123 fixed
|
||||
""".trimIndent(),
|
||||
"""
|
||||
Header IJPL-42 header
|
||||
|
||||
Body-line-1
|
||||
Body-line-N
|
||||
|
||||
^IDEA-123 fixed
|
||||
""".trimIndent(),
|
||||
"""
|
||||
Header
|
||||
|
||||
Body-line-1
|
||||
Body-line-N
|
||||
|
||||
^IJPL-123 fixed
|
||||
""".trimIndent(),
|
||||
"""
|
||||
Header
|
||||
|
||||
Body-line-1
|
||||
Body-line-N
|
||||
|
||||
^IDEA-123 fixed
|
||||
""".trimIndent(),
|
||||
"""
|
||||
Header
|
||||
|
||||
Body-line-1
|
||||
Body-line-N
|
||||
|
||||
#KTIJ-123 fixed
|
||||
""".trimIndent(),
|
||||
"""
|
||||
Header
|
||||
|
||||
Body-line-1
|
||||
Body-line-N
|
||||
|
||||
#IDEA-123 fixed
|
||||
""".trimIndent(),
|
||||
"""
|
||||
Header
|
||||
|
||||
Body-line-1
|
||||
Body-line-N
|
||||
|
||||
Relates to #KTIJ-123
|
||||
""".trimIndent(),
|
||||
"""
|
||||
Header
|
||||
|
||||
Body-line-1
|
||||
Body-line-N
|
||||
|
||||
Relates to #IDEA-123
|
||||
""".trimIndent(),
|
||||
"""
|
||||
Header
|
||||
|
||||
Body-line-1
|
||||
Body-line-N
|
||||
|
||||
^WHATEVER-123 fixed
|
||||
""".trimIndent(),
|
||||
"""
|
||||
Header
|
||||
|
||||
Body-line-1
|
||||
Body-line-N
|
||||
|
||||
#WHATEVER-123 fixed
|
||||
""".trimIndent(),
|
||||
"""
|
||||
Header
|
||||
|
||||
Body-line-1
|
||||
Body-line-N
|
||||
|
||||
Relates to #WHATEVER-123
|
||||
""".trimIndent(),
|
||||
"""
|
||||
[subsystem] refactoring: rename a to b
|
||||
|
||||
Explains why it is needed.
|
||||
""".trimIndent(),
|
||||
|
||||
"test thing", "test: thing", "[test] thing", "Test thing",
|
||||
"tests thing", "tests: thing", "[tests] thing",
|
||||
"cleanup thing", "cleanup: thing", "[cleanup] thing", "Cleanup stuff",
|
||||
"clean up thing", "clean up: thing", "[clean up] thing", "Clean Up stuff",
|
||||
"docs thing", "docs: thing", "[docs] thing", "Docs thing",
|
||||
"doc thing", "doc: thing", "[doc] thing", "Doc very much",
|
||||
"typo thing", "typo: thing", "[typo] thing",
|
||||
"format thing", "format: thing", "[format] thing",
|
||||
"style thing", "style: thing", "[style] thing",
|
||||
"refactor this thing", "refactor: this thing",
|
||||
"WIP", "[WIP] do stuff", "Add thingies WIP", "wip", "(wip) hoho", "wip: haha",
|
||||
"""
|
||||
WIP
|
||||
|
||||
Some additional remarks.
|
||||
""".trimIndent(),
|
||||
|
||||
"Cleanup (reason)",
|
||||
"[subsystem][tests] new tests",
|
||||
"[subsystem] docs: fix typo",
|
||||
"[smth][refactoring] do stuff",
|
||||
|
||||
"[testFramework] whatever",
|
||||
"[test framework] whatever",
|
||||
"test framework",
|
||||
"Rename .java to .kt"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Parameter
|
||||
lateinit var commitMessage: String
|
||||
|
||||
@Test
|
||||
fun testThatCommitMessageIsValid() {
|
||||
assert(prePushHandler.isCommitMessageCorrect(commitMessage)) {
|
||||
"The following commit message was considered invalid: $commitMessage"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(Parameterized::class)
|
||||
class InvalidCommitMessages {
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
fun provideTestParameters(): Iterable<String> {
|
||||
return listOf(
|
||||
"",
|
||||
"IJPL",
|
||||
"IJPL-",
|
||||
"IJPL-one",
|
||||
"IJPL 1",
|
||||
"IJPL111",
|
||||
"Text IJPL Text",
|
||||
"something-something",
|
||||
"2-fold",
|
||||
"AB-RA-CA-DA-BRA-1",
|
||||
""""
|
||||
Header
|
||||
|
||||
Body-line-1
|
||||
Body-line-N
|
||||
""".trimIndent(),
|
||||
"""
|
||||
No explanation
|
||||
|
||||
Test added
|
||||
""".trimIndent(),
|
||||
"""
|
||||
No explanation
|
||||
|
||||
WIP
|
||||
""".trimIndent(),
|
||||
|
||||
"test", "test:", "[test]", "test ", "add test", "drop test",
|
||||
"tests", "tests:", "[tests]", "tests ", "add tests", "drop tests",
|
||||
"cleanup", "cleanup:", "[cleanup]", "cleanup ", "do cleanup",
|
||||
"clean up", "clean up:", "[clean up]", "clean up ", "do clean up",
|
||||
"docs", "docs:", "[docs]", "docs ", "add docs",
|
||||
"doc", "doc:", "[doc]", "doc ", "add doc",
|
||||
"typo", "typo:", "[typo]", "typo ", "fix typo",
|
||||
"format", "format:", "[format]", "fix format", "fix formatting",
|
||||
"style", "style:", "[style]", "fix style",
|
||||
|
||||
"stuff", "stuff:", "[stuff]", "very important stuff",
|
||||
"refactor", "refactor:", "[refactor]",
|
||||
"refactoring", "refactoring:", "[refactoring]",
|
||||
"wipe", "swipe", "wipe the db",
|
||||
|
||||
"[subsystem] Do very important stuff very very important",
|
||||
"platform: add 'thing' here and there",
|
||||
"subsystem tests: use junit5 instead of junit4",
|
||||
"subsystem: cleanup",
|
||||
"cool: 5 new tests",
|
||||
"Fix test",
|
||||
"[subsystem] docs",
|
||||
"null",
|
||||
|
||||
"IJ-CR-160532 do not highlight parser errors twice for java",
|
||||
"IJ-MR-123", "IJ-CR-0",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Parameter
|
||||
lateinit var commitMessage: String
|
||||
|
||||
@Test
|
||||
fun testThatCommitMessageIsValid() {
|
||||
assert(!prePushHandler.isCommitMessageCorrect(commitMessage)) {
|
||||
"The following commit message was considered as valid: $commitMessage"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ContributingMdCommitMessagesAreValid {
|
||||
@Test
|
||||
fun testCommitMessagesFromContributingMd() {
|
||||
val contributingFile = Path.of(PathManager.getCommunityHomePath()) / "CONTRIBUTING.md"
|
||||
assert(contributingFile.exists()) { "CONTRIBUTING.md file not found at expected location" }
|
||||
|
||||
val content = contributingFile.readText()
|
||||
val commitMessages = extractCommitMessagesFromMarkdown(content)
|
||||
|
||||
assert(commitMessages.isNotEmpty()) { "No commit messages found in CONTRIBUTING.md" }
|
||||
|
||||
commitMessages.forEach { commitMessage ->
|
||||
assert(prePushHandler.isCommitMessageCorrect(commitMessage)) {
|
||||
"Commit message from CONTRIBUTING.md is invalid: '$commitMessage'"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractCommitMessagesFromMarkdown(content: String): List<String> {
|
||||
val codeBlockRegex = Regex("```(.*?)```", RegexOption.DOT_MATCHES_ALL)
|
||||
val commitMessages = mutableListOf<String>()
|
||||
|
||||
codeBlockRegex.findAll(content).forEach { match ->
|
||||
val codeBlock = match.groupValues[1].trim()
|
||||
|
||||
if (codeBlock.contains("[<") && codeBlock.contains(">]")) {
|
||||
return@forEach
|
||||
}
|
||||
|
||||
if (codeBlock.isNotEmpty()) {
|
||||
commitMessages.add(codeBlock)
|
||||
}
|
||||
}
|
||||
|
||||
return commitMessages
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val prePushHandler = IntelliJMonorepoPrePushHandler()
|
||||
private val tempDir: String = System.getProperty("java.io.tmpdir")
|
||||
private const val COMMUNITY_PLATFORM = "community/platform/"
|
||||
private const val COMMUNITY = "community/"
|
||||
|
||||
private fun pathAt(path: String): Path {
|
||||
return Paths.get(tempDir, *path.split("/").filterNot { it.isEmpty() }.toTypedArray())
|
||||
}
|
||||
@@ -7,7 +7,6 @@
|
||||
<orderEntry type="module" module-name="intellij.devkit" scope="RUNTIME" />
|
||||
<orderEntry type="module" module-name="intellij.devkit.core" scope="RUNTIME" />
|
||||
<orderEntry type="module" module-name="intellij.devkit.debugger" scope="RUNTIME" />
|
||||
<orderEntry type="module" module-name="intellij.devkit.git" scope="RUNTIME" />
|
||||
<orderEntry type="module" module-name="intellij.devkit.gradle" scope="RUNTIME" />
|
||||
<orderEntry type="module" module-name="intellij.devkit.i18n" scope="RUNTIME" />
|
||||
<orderEntry type="module" module-name="intellij.devkit.intelliLang" scope="RUNTIME" />
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
- name: intellij.devkit
|
||||
contentModules:
|
||||
- name: intellij.devkit.core
|
||||
- name: intellij.devkit.git
|
||||
- name: intellij.devkit.gradle
|
||||
- name: intellij.devkit.i18n
|
||||
- name: intellij.devkit.intelliLang
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
<content namespace="jetbrains">
|
||||
<module name="intellij.devkit.core"/>
|
||||
<module name="intellij.devkit.compose"/>
|
||||
<module name="intellij.devkit.git"/>
|
||||
<module name="intellij.devkit.gradle"/>
|
||||
<module name="intellij.devkit.i18n"/>
|
||||
<module name="intellij.devkit.intelliLang"/>
|
||||
|
||||
Reference in New Issue
Block a user