1 // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package git4idea.index.actions
4 import com.intellij.openapi.actionSystem.AnActionEvent
5 import com.intellij.openapi.actionSystem.Presentation
6 import com.intellij.openapi.project.Project
7 import git4idea.conflicts.GitMergeHandler
8 import git4idea.conflicts.acceptConflictSide
9 import git4idea.conflicts.getConflictOperationLock
10 import git4idea.conflicts.showMergeWindow
11 import git4idea.i18n.GitBundle
12 import git4idea.index.ui.*
13 import git4idea.repo.GitConflict
14 import org.jetbrains.annotations.Nls
15 import java.util.function.Supplier
16 import kotlin.streams.asSequence
18 class GitAcceptTheirsAction : GitAcceptConflictSideAction(true)
19 class GitAcceptYoursAction : GitAcceptConflictSideAction(false)
21 abstract class GitConflictAction(text: Supplier<@Nls String>) :
22 GitFileStatusNodeAction(text, Presentation.NULL_STRING, null) {
24 override fun update(e: AnActionEvent) {
25 val project = e.project
26 val statusInfoStream = e.getData(GIT_FILE_STATUS_NODES_STREAM)
27 if (project == null || statusInfoStream == null || !statusInfoStream.anyMatch(this::matches)) {
28 e.presentation.isEnabledAndVisible = false
32 e.presentation.isVisible = true
33 e.presentation.isEnabled = isEnabled(project,
34 e.getRequiredData(GIT_FILE_STATUS_NODES_STREAM).asSequence().mapNotNull { it.createConflict() })
37 override fun matches(statusNode: GitFileStatusNode): Boolean = statusNode.kind == NodeKind.CONFLICTED
39 override fun perform(project: Project, nodes: List<GitFileStatusNode>) {
40 perform(project, createMergeHandler(project), nodes.mapNotNull { it.createConflict() })
43 protected open fun isEnabled(project: Project, conflicts: Sequence<GitConflict>): Boolean {
44 return conflicts.any { conflict -> !getConflictOperationLock(project, conflict).isLocked }
47 protected abstract fun perform(project: Project, handler: GitMergeHandler, conflicts: List<GitConflict>)
50 abstract class GitAcceptConflictSideAction(private val takeTheirs: Boolean) : GitConflictAction(getActionText(takeTheirs)) {
51 override fun perform(project: Project, handler: GitMergeHandler, conflicts: List<GitConflict>) {
52 acceptConflictSide(project, createMergeHandler(project), conflicts, takeTheirs, project::isReversedRoot)
56 private fun getActionText(takeTheirs: Boolean): Supplier<@Nls String> {
57 return if (takeTheirs) GitBundle.messagePointer("conflicts.accept.theirs.action.text")
58 else GitBundle.messagePointer("conflicts.accept.yours.action.text")
61 class GitMergeConflictAction : GitConflictAction(GitBundle.messagePointer("action.Git.Merge.text")) {
63 override fun isEnabled(project: Project, conflicts: Sequence<GitConflict>): Boolean {
64 val handler = createMergeHandler(project)
65 return conflicts.any { conflict ->
66 !getConflictOperationLock(project, conflict).isLocked && handler.canResolveConflict(conflict)
70 override fun perform(project: Project, handler: GitMergeHandler, conflicts: List<GitConflict>) {
71 showMergeWindow(project, handler, conflicts, project::isReversedRoot)