| /* |
| * Copyright 2000-2009 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. |
| */ |
| package git4idea.merge; |
| |
| import com.intellij.history.Label; |
| import com.intellij.history.LocalHistory; |
| import com.intellij.ide.util.ElementsChooser; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.vcs.AbstractVcsHelper; |
| import com.intellij.openapi.vcs.ProjectLevelVcsManager; |
| import com.intellij.openapi.vcs.TransactionRunnable; |
| import com.intellij.openapi.vcs.VcsException; |
| import com.intellij.openapi.vcs.ex.ProjectLevelVcsManagerEx; |
| import com.intellij.openapi.vcs.update.ActionInfo; |
| import com.intellij.openapi.vcs.update.FileGroup; |
| import com.intellij.openapi.vcs.update.UpdateInfoTree; |
| import com.intellij.openapi.vcs.update.UpdatedFiles; |
| import com.intellij.openapi.vfs.LocalFileSystem; |
| import com.intellij.openapi.vfs.VfsUtilCore; |
| import com.intellij.openapi.vfs.VirtualFile; |
| import com.intellij.util.ui.UIUtil; |
| import git4idea.GitRevisionNumber; |
| import git4idea.GitUtil; |
| import git4idea.GitVcs; |
| import git4idea.actions.GitRepositoryAction; |
| import git4idea.i18n.GitBundle; |
| import git4idea.repo.GitRepositoryFiles; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import java.io.File; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.List; |
| |
| /** |
| * Utilities for merge |
| */ |
| public class GitMergeUtil { |
| /** |
| * The item representing default strategy |
| */ |
| public static final String DEFAULT_STRATEGY = GitBundle.getString("merge.default.strategy"); |
| |
| /** |
| * A private constructor for utility class |
| */ |
| private GitMergeUtil() { |
| } |
| |
| |
| /** |
| * Get a list of merge strategies for the specified branch count |
| * |
| * @param branchCount a number of branches to merge |
| * @return an array of strategy names |
| */ |
| @NonNls |
| public static String[] getMergeStrategies(int branchCount) { |
| if (branchCount < 0) { |
| throw new IllegalArgumentException("Branch count must be non-negative: " + branchCount); |
| } |
| switch (branchCount) { |
| case 0: |
| return new String[]{DEFAULT_STRATEGY}; |
| case 1: |
| return new String[]{DEFAULT_STRATEGY, "resolve", "recursive", "octopus", "ours", "subtree"}; |
| default: |
| return new String[]{DEFAULT_STRATEGY, "octopus", "ours"}; |
| } |
| } |
| |
| /** |
| * Setup strategies combobox. The set of strategies changes according to amount of selected elements in branchChooser. |
| * |
| * @param branchChooser a branch chooser |
| * @param strategy a strategy selector |
| */ |
| public static void setupStrategies(final ElementsChooser<String> branchChooser, final JComboBox strategy) { |
| final ElementsChooser.ElementsMarkListener<String> listener = new ElementsChooser.ElementsMarkListener<String>() { |
| private void updateStrategies(final List<String> elements) { |
| strategy.removeAllItems(); |
| for (String s : getMergeStrategies(elements.size())) { |
| strategy.addItem(s); |
| } |
| strategy.setSelectedItem(DEFAULT_STRATEGY); |
| } |
| |
| public void elementMarkChanged(final String element, final boolean isMarked) { |
| final List<String> elements = branchChooser.getMarkedElements(); |
| if (elements.size() == 0) { |
| strategy.setEnabled(false); |
| updateStrategies(elements); |
| } |
| else { |
| strategy.setEnabled(true); |
| updateStrategies(elements); |
| } |
| } |
| }; |
| listener.elementMarkChanged(null, true); |
| branchChooser.addElementsMarkListener(listener); |
| } |
| |
| /** |
| * Show updates caused by git operation |
| * |
| * @param project the context project |
| * @param exceptions the exception list |
| * @param root the git root |
| * @param currentRev the revision before update |
| * @param beforeLabel the local history label before update |
| * @param actionName the action name |
| * @param actionInfo the information about the action |
| */ |
| public static void showUpdates(GitRepositoryAction action, |
| final Project project, |
| final List<VcsException> exceptions, |
| final VirtualFile root, |
| final GitRevisionNumber currentRev, |
| final Label beforeLabel, |
| final String actionName, |
| final ActionInfo actionInfo) { |
| final UpdatedFiles files = UpdatedFiles.create(); |
| MergeChangeCollector collector = new MergeChangeCollector(project, root, currentRev); |
| collector.collect(files, exceptions); |
| if (exceptions.size() != 0) { |
| return; |
| } |
| action.delayTask(new TransactionRunnable() { |
| public void run(List<VcsException> exceptionList) { |
| UIUtil.invokeLaterIfNeeded(new Runnable() { |
| @Override |
| public void run() { |
| ProjectLevelVcsManagerEx manager = (ProjectLevelVcsManagerEx)ProjectLevelVcsManager.getInstance(project); |
| UpdateInfoTree tree = manager.showUpdateProjectInfo(files, actionName, actionInfo, false); |
| tree.setBefore(beforeLabel); |
| tree.setAfter(LocalHistory.getInstance().putSystemLabel(project, "After update")); |
| } |
| }); |
| } |
| }); |
| final Collection<String> unmergedNames = files.getGroupById(FileGroup.MERGED_WITH_CONFLICT_ID).getFiles(); |
| if (!unmergedNames.isEmpty()) { |
| action.delayTask(new TransactionRunnable() { |
| public void run(List<VcsException> exceptionList) { |
| LocalFileSystem lfs = LocalFileSystem.getInstance(); |
| final ArrayList<VirtualFile> unmerged = new ArrayList<VirtualFile>(); |
| for (String fileName : unmergedNames) { |
| VirtualFile f = lfs.findFileByPath(fileName); |
| if (f != null) { |
| unmerged.add(f); |
| } |
| } |
| UIUtil.invokeLaterIfNeeded(new Runnable() { |
| @Override |
| public void run() { |
| GitVcs vcs = GitVcs.getInstance(project); |
| if (vcs != null) { |
| AbstractVcsHelper.getInstance(project).showMergeDialog(unmerged, vcs.getMergeProvider()); |
| } |
| } |
| }); |
| } |
| }); |
| } |
| } |
| |
| |
| /** |
| * @param root the vcs root |
| * @return the path to merge head file |
| */ |
| @Nullable |
| private static File getMergeHead(@NotNull VirtualFile root) { |
| File gitDir = new File(VfsUtilCore.virtualToIoFile(root), GitUtil.DOT_GIT); |
| File f = new File(gitDir, GitRepositoryFiles.MERGE_HEAD); |
| if (f.exists()) { |
| return f; |
| } |
| return null; |
| } |
| |
| /** |
| * @return true if merge is going on for the given git root, false if there is no merge operation in progress. |
| */ |
| @Deprecated |
| public static boolean isMergeInProgress(@NotNull VirtualFile root) { |
| return getMergeHead(root) != null; |
| } |
| } |