From 47248016910d1efd3dd0978473a538ab8e30a690 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 12 Feb 2017 17:23:38 +0000 Subject: [PATCH] Make "Create new branch" action available not only from the log If the log is in data context, create new branch at the selected commit. Otherwise, create branch at HEAD in the guessed root or in all roots. Fix for IDEA-164512 --- .../actions/GitCreateNewBranchAction.kt | 89 ++++++++++++++++++- 1 file changed, 85 insertions(+), 4 deletions(-) diff --git a/plugins/git4idea/src/git4idea/actions/GitCreateNewBranchAction.kt b/plugins/git4idea/src/git4idea/actions/GitCreateNewBranchAction.kt index 6d08d34a9025..e98c97057f01 100644 --- a/plugins/git4idea/src/git4idea/actions/GitCreateNewBranchAction.kt +++ b/plugins/git4idea/src/git4idea/actions/GitCreateNewBranchAction.kt @@ -15,23 +15,104 @@ */ package git4idea.actions +import com.intellij.dvcs.DvcsUtil.guessVcsRoot +import com.intellij.dvcs.branch.DvcsSyncSettings.Value.SYNC +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.actionSystem.CommonDataKeys.VIRTUAL_FILE +import com.intellij.openapi.project.DumbAwareAction +import com.intellij.openapi.project.Project import com.intellij.vcs.log.Hash +import com.intellij.vcs.log.VcsLogDataKeys +import git4idea.GitUtil.HEAD +import git4idea.GitUtil.getRepositoryManager import git4idea.branch.GitBranchUtil.getNewBranchNameFromUser import git4idea.branch.GitBrancher +import git4idea.config.GitVcsSettings import git4idea.repo.GitRepository -class GitCreateNewBranchAction : GitLogSingleCommitAction() { +internal class GitCreateNewBranchAction : DumbAwareAction() { - override fun actionPerformed(repository: GitRepository, commit: Hash) { + override fun actionPerformed(e: AnActionEvent) { + val data = collectData(e) + when (data) { + is Data.WithCommit -> createBranchStartingFrom(data.repository, data.hash) + is Data.NoCommit -> createBranch(data.project, data.repositories) + } + } + + override fun update(e: AnActionEvent) { + super.update(e) + val data = collectData(e) + when (data) { + is Data.Invisible -> e.presentation.isEnabledAndVisible = false + is Data.Disabled -> { + e.presentation.isVisible = true + e.presentation.isEnabled = false + } + else -> e.presentation.isEnabledAndVisible = true + } + } + + private sealed class Data { + class Invisible : Data() + class Disabled : Data() + class WithCommit(val repository: GitRepository, val hash: Hash) : Data() + class NoCommit(val project: Project, val repositories: List) : Data() + } + + private fun collectData(e: AnActionEvent): Data { + val project = e.project ?: return Data.Invisible() + val manager = getRepositoryManager(project) + + val log = e.getData(VcsLogDataKeys.VCS_LOG) + if (log != null) { + val commits = log.selectedCommits + if (commits.isEmpty()) return Data.Invisible() + if (commits.size > 1) return Data.Disabled() + val commit = commits.first() + val repository = manager.getRepositoryForRoot(commit.root) + if (repository != null) { + return Data.WithCommit(repository, commit.hash) + } + } + + val repositories = + if (manager.moreThanOneRoot()) { + if (GitVcsSettings.getInstance(project).syncSetting == SYNC) manager.repositories + else { + val repository = manager.getRepositoryForRoot(guessVcsRoot(project, e.getData(VIRTUAL_FILE))) + repository?.let { listOf(repository) } + } + } + else listOf(manager.repositories.first()) + + if (repositories == null || repositories.any { it.isFresh }) return Data.Invisible() + return Data.NoCommit(project, repositories) + } + + fun createBranch(project: Project, repositories: List) { + val options = getNewBranchNameFromUser(project, repositories, "Create New Branch") + if (options != null) { + val brancher = GitBrancher.getInstance(project) + if (options.checkout) { + brancher.checkoutNewBranch(options.name, repositories) + } + else { + brancher.createBranch(options.name, repositories.map { it to HEAD }.toMap()) + } + } + } + + fun createBranchStartingFrom(repository: GitRepository, commit: Hash) { val project = repository.project - val options = getNewBranchNameFromUser(project, setOf(repository), "Checkout New Branch From " + commit.toShortString()) + val options = getNewBranchNameFromUser(project, setOf(repository), "Create New Branch From ${commit.toShortString()}") if (options != null) { val brancher = GitBrancher.getInstance(project) if (options.checkout) { brancher.checkoutNewBranchStartingFrom(options.name, commit.asString(), listOf(repository), null) } else { - brancher.createBranch(options.name, mapOf(repository to commit.asString())); + brancher.createBranch(options.name, mapOf(repository to commit.asString())) } } }