diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 3cbcbb2df5ac..b6f0c5ac1ff5 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -1225,6 +1225,8 @@ git.force.commit.using.staging.area=true git.force.commit.using.staging.area.description=When enabled, perform all git commits by updating staging area. If disabled, use `git commit --only` when possible. git.clone.recurse.submodules=true git.clone.recurse.submodules.description=When enabled, Checkout from Git calls `git clone --recurse-submodules`, i.e. clones the main repository with all submodules if there are any. +git.compare.branches.as.tab=false +git.compare.branches.as.tab.description=Compares branches by showing a log tab filtered by `HEAD..branch` instead of showing a dialog. git.read.content.with.textconv=false git.read.content.with.textconv.description=Apply `textconv` transformations when reading file content from git. (overrides "git.read.content.with.filters" option) git.read.content.with.filters=true diff --git a/plugins/git4idea/resources/messages/GitBundle.properties b/plugins/git4idea/resources/messages/GitBundle.properties index a977a3610017..eb07b80b888e 100644 --- a/plugins/git4idea/resources/messages/GitBundle.properties +++ b/plugins/git4idea/resources/messages/GitBundle.properties @@ -775,6 +775,10 @@ branch.checking.out.new.branch.process=Checking out new branch {0}... branch.creating.branch.process=Creating branch {0}... branch.checking.out.branch.from.process=Checking out {0} from {1}... branch.checking.out.process=Checking out {0}... +branch.compare.progress=Comparing with {0}... +compare.branches.error=Can't Compare with Branch +compare.branches.no.changes.message.title=No Changes Detected +compare.branches.no.changes.message.description=There are no changes between {0} and {1} branch.not.fully.merged.dialog.repository.label=Repository: branch.not.fully.merged.dialog.title=Branch Was Not Fully Merged @@ -794,4 +798,4 @@ show.diff.between.dialog.could.not.load.diff.with.branch.error=Couldn''t load di annotations.options.detect.movements.across.files=Detect Movements Across Files annotations.options.detect.movements.within.file=Detect Movements Within File annotations.options.ignore.whitespaces=Ignore Whitespaces -annotations.options.group=Options \ No newline at end of file +annotations.options.group=Options diff --git a/plugins/git4idea/src/git4idea/branch/GitBranchWorker.java b/plugins/git4idea/src/git4idea/branch/GitBranchWorker.java index 0f8d17bbe0bb..8fafa02a235a 100644 --- a/plugins/git4idea/src/git4idea/branch/GitBranchWorker.java +++ b/plugins/git4idea/src/git4idea/branch/GitBranchWorker.java @@ -1,27 +1,18 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// 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. package git4idea.branch; import com.intellij.dvcs.repo.Repository; +import com.intellij.dvcs.ui.CompareBranchesDialog; +import com.intellij.dvcs.util.CommitCompareInfo; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.VcsNotifier; import com.intellij.openapi.vcs.changes.Change; import com.intellij.util.containers.ContainerUtil; +import git4idea.GitCommit; import git4idea.GitLocalBranch; import git4idea.GitUtil; import git4idea.GitVcs; @@ -29,8 +20,11 @@ import git4idea.changes.GitChangeUtils; import git4idea.commands.Git; import git4idea.commands.GitCommandResult; import git4idea.i18n.GitBundle; +import git4idea.history.GitHistoryUtils; import git4idea.rebase.GitRebaseUtils; import git4idea.repo.GitRepository; +import git4idea.ui.branch.GitCompareBranchesHelper; +import git4idea.util.GitLocalCommitCompareInfo; import org.jetbrains.annotations.NotNull; import java.util.Collection; @@ -166,12 +160,49 @@ public final class GitBranchWorker { new GitRenameBranchOperation(myProject, myGit, myUiHandler, currentName, newName, repositories).execute(); } + void compare(@NotNull String branchName, @NotNull List repositories, @NotNull GitRepository selectedRepository) { + try { + CommitCompareInfo myCompareInfo = loadCommitsToCompare(repositories, branchName); + ApplicationManager.getApplication().invokeLater( + () -> displayCompareDialog(branchName, GitBranchUtil.getCurrentBranchOrRev(repositories), myCompareInfo, selectedRepository)); + } + catch (VcsException e) { + VcsNotifier.getInstance(myProject).notifyError(GitBundle.message("compare.branches.error"), e.getMessage()); + } + } + + @NotNull + private CommitCompareInfo loadCommitsToCompare(@NotNull List repositories, + @NotNull String branchName) throws VcsException { + CommitCompareInfo compareInfo = new GitLocalCommitCompareInfo(myProject, branchName); + for (GitRepository repository : repositories) { + List headToBranch = GitHistoryUtils.history(myProject, repository.getRoot(), ".." + branchName); + List branchToHead = GitHistoryUtils.history(myProject, repository.getRoot(), branchName + ".."); + compareInfo.put(repository, headToBranch, branchToHead); + + compareInfo.putTotalDiff(repository, loadTotalDiff(repository, branchName)); + } + return compareInfo; + } + @NotNull public static Collection loadTotalDiff(@NotNull Repository repository, @NotNull String branchName) throws VcsException { // return git diff between current working directory and branchName: working dir should be displayed as a 'left' one (base) return GitChangeUtils.getDiffWithWorkingDir(repository.getProject(), repository.getRoot(), branchName, null, true); } + private void displayCompareDialog(@NotNull String branchName, @NotNull String currentBranch, @NotNull CommitCompareInfo compareInfo, + @NotNull GitRepository selectedRepository) { + if (compareInfo.isEmpty()) { + Messages.showInfoMessage(myProject, GitBundle.message("compare.branches.no.changes.message.description", currentBranch, branchName), + GitBundle.message("compare.branches.no.changes.message.title")); + } + else { + new CompareBranchesDialog(new GitCompareBranchesHelper(myProject), + branchName, currentBranch, compareInfo, selectedRepository, false).show(); + } + } + private static void updateInfo(@NotNull Collection repositories) { for (GitRepository repository : repositories) { repository.update(); diff --git a/plugins/git4idea/src/git4idea/branch/GitBrancher.java b/plugins/git4idea/src/git4idea/branch/GitBrancher.java index 15fa6195cbb0..2b0d2f82e8db 100644 --- a/plugins/git4idea/src/git4idea/branch/GitBrancher.java +++ b/plugins/git4idea/src/git4idea/branch/GitBrancher.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// 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. package git4idea.branch; import com.intellij.openapi.components.ServiceManager; @@ -156,7 +142,9 @@ public interface GitBrancher { /** * Compares commits from the HEAD with the specified branch. */ - void compare(@NotNull String branchName, @NotNull List repositories); + void compare(@NotNull String branchName, + @NotNull List repositories, + @NotNull GitRepository selectedRepository); /** * Compares the current working tree with its state in the selected branch. diff --git a/plugins/git4idea/src/git4idea/branch/GitBrancherImpl.java b/plugins/git4idea/src/git4idea/branch/GitBrancherImpl.java index 9070c45c631c..8c888f351274 100644 --- a/plugins/git4idea/src/git4idea/branch/GitBrancherImpl.java +++ b/plugins/git4idea/src/git4idea/branch/GitBrancherImpl.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// 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. package git4idea.branch; import com.intellij.openapi.application.Application; @@ -21,6 +7,7 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.util.registry.Registry; import git4idea.GitVcs; import git4idea.commands.Git; import git4idea.i18n.GitBundle; @@ -158,8 +145,20 @@ class GitBrancherImpl implements GitBrancher { } @Override - public void compare(@NotNull String branchName, @NotNull List repositories) { - new GitCompareBranchesUi(myProject, repositories, branchName).create(); + public void compare(@NotNull String branchName, + @NotNull List repositories, + @NotNull GitRepository selectedRepository) { + if (Registry.is("git.compare.branches.as.tab")) { + new GitCompareBranchesUi(myProject, repositories, branchName).create(); + } + else { + new CommonBackgroundTask(myProject, GitBundle.message("branch.compare.progress", branchName), null) { + @Override + public void execute(@NotNull ProgressIndicator indicator) { + newWorker(indicator).compare(branchName, repositories, selectedRepository); + } + }.runInBackground(); + } } @Override diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java b/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java index 1418df38331d..6fb65ba462af 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java +++ b/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java @@ -270,7 +270,7 @@ public class GitBranchPopupActions { new CheckoutAsNewBranch(myProject, myRepositories, myBranchName), new CheckoutWithRebaseAction(myProject, myRepositories, myBranchName), new Separator(), - new CompareAction(myProject, myRepositories, myBranchName), + new CompareAction(myProject, myRepositories, myBranchName, mySelectedRepository), new ShowDiffWithBranchAction(myProject, myRepositories, myBranchName), new Separator(), new RebaseAction(myProject, myRepositories, myBranchName), @@ -480,7 +480,7 @@ public class GitBranchPopupActions { new CheckoutRemoteBranchAction(myProject, myRepositories, myBranchName), new CheckoutAsNewBranch(myProject, myRepositories, myBranchName), new Separator(), - new CompareAction(myProject, myRepositories, myBranchName), + new CompareAction(myProject, myRepositories, myBranchName, mySelectedRepository), new ShowDiffWithBranchAction(myProject, myRepositories, myBranchName), new Separator(), new RebaseAction(myProject, myRepositories, myBranchName), @@ -619,12 +619,17 @@ public class GitBranchPopupActions { private final Project myProject; private final List myRepositories; private final String myBranchName; + private final GitRepository mySelectedRepository; - CompareAction(@NotNull Project project, @NotNull List repositories, @NotNull String branchName) { + CompareAction(@NotNull Project project, + @NotNull List repositories, + @NotNull String branchName, + @NotNull GitRepository selectedRepository) { super(GitBundle.messagePointer("branches.compare.with.current")); myProject = project; myRepositories = repositories; myBranchName = branchName; + mySelectedRepository = selectedRepository; } @Override @@ -632,7 +637,7 @@ public class GitBranchPopupActions { FileDocumentManager.getInstance().saveAllDocuments(); GitBrancher brancher = GitBrancher.getInstance(myProject); - brancher.compare(myBranchName, myRepositories); + brancher.compare(myBranchName, myRepositories, mySelectedRepository); } @Override diff --git a/plugins/git4idea/src/git4idea/ui/branch/dashboard/BranchesDashboardActions.kt b/plugins/git4idea/src/git4idea/ui/branch/dashboard/BranchesDashboardActions.kt index 0468f17dcd66..4190ad71e6ae 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/dashboard/BranchesDashboardActions.kt +++ b/plugins/git4idea/src/git4idea/ui/branch/dashboard/BranchesDashboardActions.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2019 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. +// 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. package git4idea.ui.branch.dashboard import com.intellij.dvcs.DvcsUtil @@ -18,6 +18,7 @@ import com.intellij.vcs.log.ui.VcsLogInternalDataKeys import git4idea.GitUtil import git4idea.actions.GitFetch import git4idea.branch.GitBranchType +import git4idea.branch.GitBranchUtil import git4idea.branch.GitBrancher import git4idea.config.GitVcsSettings import git4idea.fetch.GitFetchResult @@ -200,15 +201,19 @@ internal object BranchesDashboardActions { e.presentation.isEnabled = false e.presentation.description = message("action.Git.Update.Selected.description.select.non.current") } + else if (GitBranchUtil.getCurrentRepository(project) == null) { + e.presentation.isEnabled = false + } } override fun actionPerformed(e: AnActionEvent) { val branches = e.getData(GIT_BRANCHES)!! val project = e.project!! val gitBrancher = GitBrancher.getInstance(project) + val currentRepository = GitBranchUtil.getCurrentRepository(project)!! for (branch in branches.filterNot(BranchInfo::isCurrent)) { - gitBrancher.compare(branch.branchName, branch.repositories) + gitBrancher.compare(branch.branchName, branch.repositories, currentRepository) } } }