From bd8a844a465908569bf53eb2a787d266f665b4b8 Mon Sep 17 00:00:00 2001 From: Piotr Tomiak Date: Mon, 3 Nov 2025 14:39:20 +0100 Subject: [PATCH] IJI-3207 DevKit: remove intellij.devkit.git, which contained only pre-push handlers logic (cherry picked from commit a9d06e72ef255c3eaef4e6f7d3c4c2f0680eb67f) IJ-CR-181845 GitOrigin-RevId: c6d1f65d1400af3096f3db5c6673118dc0257122 --- .idea/modules.xml | 1 - build/bazel-generated-file-list.txt | 1 - plugins/devkit/BUILD.bazel | 2 - .../resources/intellij.devkit.core.xml | 9 - .../devkit/intellij.devkit.git/BUILD.bazel | 107 ----- .../intellij.devkit.git.iml | 29 -- .../resources/intellij.devkit.git.xml | 12 - .../messages/DevKitGitBundle.properties | 28 -- .../AbstractIntelliJProjectPrePushHandler.kt | 78 ---- .../src/DevKitGitBundle.java | 30 -- .../src/IssueIDPrePushHandler.kt | 122 ------ .../src/intellijPrePushHandlers.kt | 140 ------- .../src/kotlinPrePushHandlers.kt | 76 ---- .../IntelliJMonorepoPrePushHandlerTest.kt | 387 ------------------ .../intellij.devkit.plugin.main.noKotlin.iml | 1 - plugins/devkit/plugin-content.yaml | 1 - plugins/devkit/resources/META-INF/plugin.xml | 1 - 17 files changed, 1025 deletions(-) delete mode 100644 plugins/devkit/intellij.devkit.git/BUILD.bazel delete mode 100644 plugins/devkit/intellij.devkit.git/intellij.devkit.git.iml delete mode 100644 plugins/devkit/intellij.devkit.git/resources/intellij.devkit.git.xml delete mode 100644 plugins/devkit/intellij.devkit.git/resources/messages/DevKitGitBundle.properties delete mode 100644 plugins/devkit/intellij.devkit.git/src/AbstractIntelliJProjectPrePushHandler.kt delete mode 100644 plugins/devkit/intellij.devkit.git/src/DevKitGitBundle.java delete mode 100644 plugins/devkit/intellij.devkit.git/src/IssueIDPrePushHandler.kt delete mode 100644 plugins/devkit/intellij.devkit.git/src/intellijPrePushHandlers.kt delete mode 100644 plugins/devkit/intellij.devkit.git/src/kotlinPrePushHandlers.kt delete mode 100644 plugins/devkit/intellij.devkit.git/test/IntelliJMonorepoPrePushHandlerTest.kt diff --git a/.idea/modules.xml b/.idea/modules.xml index 30e7cb9fd59f..1ace0dfb8abe 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -379,7 +379,6 @@ - diff --git a/build/bazel-generated-file-list.txt b/build/bazel-generated-file-list.txt index 0797b96b0e8c..fe6e56b03590 100644 --- a/build/bazel-generated-file-list.txt +++ b/build/bazel-generated-file-list.txt @@ -872,7 +872,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 diff --git a/plugins/devkit/BUILD.bazel b/plugins/devkit/BUILD.bazel index 5e5c32ce5890..4e9b79faf686 100644 --- a/plugins/devkit/BUILD.bazel +++ b/plugins/devkit/BUILD.bazel @@ -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", diff --git a/plugins/devkit/devkit-core/resources/intellij.devkit.core.xml b/plugins/devkit/devkit-core/resources/intellij.devkit.core.xml index 970ac19ef926..0ba267dc6ab4 100644 --- a/plugins/devkit/devkit-core/resources/intellij.devkit.core.xml +++ b/plugins/devkit/devkit-core/resources/intellij.devkit.core.xml @@ -693,10 +693,6 @@ - - - - - diff --git a/plugins/devkit/intellij.devkit.git/BUILD.bazel b/plugins/devkit/intellij.devkit.git/BUILD.bazel deleted file mode 100644 index 63c259f841f6..000000000000 --- a/plugins/devkit/intellij.devkit.git/BUILD.bazel +++ /dev/null @@ -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 \ No newline at end of file diff --git a/plugins/devkit/intellij.devkit.git/intellij.devkit.git.iml b/plugins/devkit/intellij.devkit.git/intellij.devkit.git.iml deleted file mode 100644 index 2fb99cb3cb6f..000000000000 --- a/plugins/devkit/intellij.devkit.git/intellij.devkit.git.iml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/plugins/devkit/intellij.devkit.git/resources/intellij.devkit.git.xml b/plugins/devkit/intellij.devkit.git/resources/intellij.devkit.git.xml deleted file mode 100644 index 6422da28bff0..000000000000 --- a/plugins/devkit/intellij.devkit.git/resources/intellij.devkit.git.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/plugins/devkit/intellij.devkit.git/resources/messages/DevKitGitBundle.properties b/plugins/devkit/intellij.devkit.git/resources/messages/DevKitGitBundle.properties deleted file mode 100644 index b767d641e4e4..000000000000 --- a/plugins/devkit/intellij.devkit.git/resources/messages/DevKitGitBundle.properties +++ /dev/null @@ -1,28 +0,0 @@ -push.commit.message.lacks.issue.reference.body=\ - Commits listed below change the Kotlin IDE plugin sources. According to the rules of the plugin team, \ - all meaningful commits \ - should reference a {0} issue in their message. Do you still want to push as is? \ -
{1}
\ - -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=\ - 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.

\ - Create an issue or use any IDE-related YT ticket ID.

\ - - -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=\ - Commits listed below change the Kotlin Build Tools code.

\ - According to the rules of the Kotlin Build Tools team, \ - all commits to their codebase have to pass mandatory pre-review.\ -
{0}
\ - \ No newline at end of file diff --git a/plugins/devkit/intellij.devkit.git/src/AbstractIntelliJProjectPrePushHandler.kt b/plugins/devkit/intellij.devkit.git/src/AbstractIntelliJProjectPrePushHandler.kt deleted file mode 100644 index ad6bfb49b4e4..000000000000 --- a/plugins/devkit/intellij.devkit.git/src/AbstractIntelliJProjectPrePushHandler.kt +++ /dev/null @@ -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, 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.anyIn(paths: List, pathsToIgnore: List): 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.toHtml(): @NlsSafe String = - joinToString("
") { commit -> - "${commit.id.toShortString()}: ${commit.subject}" - } - - internal fun invokeAndWait(modalityState: ModalityState, computable: () -> T): T { - val ref = AtomicReference() - ApplicationManager.getApplication().invokeAndWait({ ref.set(computable.invoke()) }, modalityState) - return ref.get() - } - } -} \ No newline at end of file diff --git a/plugins/devkit/intellij.devkit.git/src/DevKitGitBundle.java b/plugins/devkit/intellij.devkit.git/src/DevKitGitBundle.java deleted file mode 100644 index bcacfd196986..000000000000 --- a/plugins/devkit/intellij.devkit.git/src/DevKitGitBundle.java +++ /dev/null @@ -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); - } -} diff --git a/plugins/devkit/intellij.devkit.git/src/IssueIDPrePushHandler.kt b/plugins/devkit/intellij.devkit.git/src/IssueIDPrePushHandler.kt deleted file mode 100644 index c3b6a42a7608..000000000000 --- a/plugins/devkit/intellij.devkit.git/src/IssueIDPrePushHandler.kt +++ /dev/null @@ -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 = listOf() - protected open val pathsToIgnore: List = 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): 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, - 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) = - "$projectId" -} \ No newline at end of file diff --git a/plugins/devkit/intellij.devkit.git/src/intellijPrePushHandlers.kt b/plugins/devkit/intellij.devkit.git/src/intellijPrePushHandlers.kt deleted file mode 100644 index 6d2a7823fef0..000000000000 --- a/plugins/devkit/intellij.devkit.git/src/intellijPrePushHandlers.kt +++ /dev/null @@ -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 = 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 = 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, - 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().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", "
${commitsInfo.replace("\n", "
")}
").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 { - return arrayOf( - commitAction, - editAction, - cancelAction - ) - } - - override fun getDimensionServiceKey(): String { - return "IntelliJPlatformCommitValidationDialog" - } -} \ No newline at end of file diff --git a/plugins/devkit/intellij.devkit.git/src/kotlinPrePushHandlers.kt b/plugins/devkit/intellij.devkit.git/src/kotlinPrePushHandlers.kt deleted file mode 100644 index 45e2ae575b16..000000000000 --- a/plugins/devkit/intellij.devkit.git/src/kotlinPrePushHandlers.kt +++ /dev/null @@ -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 = listOf("plugins/kotlin/jupyter/") - override val acceptableProjects: List = 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 = - 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 = - 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 - } -} diff --git a/plugins/devkit/intellij.devkit.git/test/IntelliJMonorepoPrePushHandlerTest.kt b/plugins/devkit/intellij.devkit.git/test/IntelliJMonorepoPrePushHandlerTest.kt deleted file mode 100644 index 423f652be6f2..000000000000 --- a/plugins/devkit/intellij.devkit.git/test/IntelliJMonorepoPrePushHandlerTest.kt +++ /dev/null @@ -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> { - 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 - - @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> { - 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 - - @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 { - 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 { - 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 { - val codeBlockRegex = Regex("```(.*?)```", RegexOption.DOT_MATCHES_ALL) - val commitMessages = mutableListOf() - - 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()) -} \ No newline at end of file diff --git a/plugins/devkit/intellij.devkit.plugin.main.noKotlin.iml b/plugins/devkit/intellij.devkit.plugin.main.noKotlin.iml index 0f6d2432369b..88c65b0c7e51 100644 --- a/plugins/devkit/intellij.devkit.plugin.main.noKotlin.iml +++ b/plugins/devkit/intellij.devkit.plugin.main.noKotlin.iml @@ -7,7 +7,6 @@ - diff --git a/plugins/devkit/plugin-content.yaml b/plugins/devkit/plugin-content.yaml index ebf3eeb65e93..6b739cf20948 100644 --- a/plugins/devkit/plugin-content.yaml +++ b/plugins/devkit/plugin-content.yaml @@ -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 diff --git a/plugins/devkit/resources/META-INF/plugin.xml b/plugins/devkit/resources/META-INF/plugin.xml index f4031b148dcd..1a396ad27b28 100644 --- a/plugins/devkit/resources/META-INF/plugin.xml +++ b/plugins/devkit/resources/META-INF/plugin.xml @@ -29,7 +29,6 @@ -