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())) } } }