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
This commit is contained in:
Kirill Likhodedov
2017-02-14 15:13:28 +00:00
parent 8ad7d251b7
commit 4724801691
@@ -15,23 +15,104 @@
*/ */
package git4idea.actions 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.Hash
import com.intellij.vcs.log.VcsLogDataKeys
import git4idea.GitUtil.HEAD
import git4idea.GitUtil.getRepositoryManager
import git4idea.branch.GitBranchUtil.getNewBranchNameFromUser import git4idea.branch.GitBranchUtil.getNewBranchNameFromUser
import git4idea.branch.GitBrancher import git4idea.branch.GitBrancher
import git4idea.config.GitVcsSettings
import git4idea.repo.GitRepository 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<GitRepository>) : 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<GitRepository>) {
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 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) { if (options != null) {
val brancher = GitBrancher.getInstance(project) val brancher = GitBrancher.getInstance(project)
if (options.checkout) { if (options.checkout) {
brancher.checkoutNewBranchStartingFrom(options.name, commit.asString(), listOf(repository), null) brancher.checkoutNewBranchStartingFrom(options.name, commit.asString(), listOf(repository), null)
} }
else { else {
brancher.createBranch(options.name, mapOf(repository to commit.asString())); brancher.createBranch(options.name, mapOf(repository to commit.asString()))
} }
} }
} }