diff options
Diffstat (limited to 'plugins/hg4idea/src/org/zmlx/hg4idea/branch')
7 files changed, 729 insertions, 0 deletions
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchAbstractAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchAbstractAction.java new file mode 100644 index 000000000000..3998dedd0cc5 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchAbstractAction.java @@ -0,0 +1,38 @@ +/* + * 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. + */ +package org.zmlx.hg4idea.branch; + +import com.intellij.openapi.project.DumbAwareAction; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; +import org.zmlx.hg4idea.repo.HgRepository; + +import java.util.List; + +public abstract class HgBranchAbstractAction extends DumbAwareAction { + @NotNull protected final Project myProject; + @NotNull protected final List<HgRepository> myRepositories; + @NotNull protected final String myBranchName; + + public HgBranchAbstractAction(@NotNull Project project, @NotNull String title, + @NotNull List<HgRepository> repositories, + @NotNull String branchName) { + super(title); + myProject = project; + myRepositories = repositories; + myBranchName = branchName; + } +}
\ No newline at end of file diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchPopup.java b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchPopup.java new file mode 100644 index 000000000000..c0d6f58d5e0e --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchPopup.java @@ -0,0 +1,119 @@ +/* + * Copyright 2000-2013 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 org.zmlx.hg4idea.branch; + +import com.intellij.dvcs.branch.DvcsBranchPopup; +import com.intellij.dvcs.repo.AbstractRepositoryManager; +import com.intellij.dvcs.ui.RootAction; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.DefaultActionGroup; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.zmlx.hg4idea.HgProjectSettings; +import org.zmlx.hg4idea.repo.HgRepository; +import org.zmlx.hg4idea.repo.HgRepositoryManager; +import org.zmlx.hg4idea.util.HgUtil; + +import javax.swing.*; +import java.util.List; + +/** + * <p> + * The popup which allows to quickly switch and control Hg branches. + * </p> + * <p> + * Use {@link #asListPopup()} to achieve the {@link com.intellij.openapi.ui.popup.ListPopup} itself. + * </p> + */ +public class HgBranchPopup extends DvcsBranchPopup<HgRepository> { + + /** + * @param currentRepository Current repository, which means the repository of the currently open or selected file. + */ + public static HgBranchPopup getInstance(@NotNull Project project, @NotNull HgRepository currentRepository) { + + HgRepositoryManager manager = HgUtil.getRepositoryManager(project); + HgProjectSettings hgProjectSettings = ServiceManager.getService(project, HgProjectSettings.class); + HgMultiRootBranchConfig hgMultiRootBranchConfig = new HgMultiRootBranchConfig(manager.getRepositories()); + + Condition<AnAction> preselectActionCondition = new Condition<AnAction>() { + @Override + public boolean value(AnAction action) { + return false; + } + }; + return new HgBranchPopup(currentRepository, manager, hgMultiRootBranchConfig, hgProjectSettings, + preselectActionCondition); + } + + private HgBranchPopup(@NotNull HgRepository currentRepository, + @NotNull HgRepositoryManager repositoryManager, + @NotNull HgMultiRootBranchConfig hgMultiRootBranchConfig, @NotNull HgProjectSettings vcsSettings, + @NotNull Condition<AnAction> preselectActionCondition) { + super(currentRepository, repositoryManager, hgMultiRootBranchConfig, vcsSettings, preselectActionCondition); + } + + protected void setCurrentBranchInfo() { + String branchText = "Current branch : "; + //always display heavy branch name for additional info // + myPopup.setAdText(branchText + myCurrentRepository.getCurrentBranch(), SwingConstants.CENTER); + } + + @Override + protected void fillWithCommonRepositoryActions(@NotNull DefaultActionGroup popupGroup, + @NotNull AbstractRepositoryManager<HgRepository> repositoryManager) { + List<HgRepository> allRepositories = repositoryManager.getRepositories(); + popupGroup.add(new HgBranchPopupActions.HgNewBranchAction(myProject, allRepositories, myCurrentRepository)); + popupGroup.addAction(new HgBranchPopupActions.HgNewBookmarkAction(myProject, allRepositories, myCurrentRepository)); + popupGroup.addAction(new HgBranchPopupActions.HgShowUnnamedHeadsForCurrentBranchAction(myProject, myCurrentRepository)); + popupGroup.addAll(createRepositoriesActions()); + + popupGroup.addSeparator("Common Branches"); + for (String branch : myMultiRootBranchConfig.getLocalBranchNames()) { + List<HgRepository> repositories = filterRepositoriesNotOnThisBranch(branch, allRepositories); + if (!repositories.isEmpty()) { + popupGroup.add(new HgCommonBranchActions(myProject, repositories, branch)); + } + } + popupGroup.addSeparator("Common Bookmarks"); + for (String branch : ((HgMultiRootBranchConfig)myMultiRootBranchConfig).getBookmarkNames()) { + List<HgRepository> repositories = filterRepositoriesNotOnThisBranch(branch, allRepositories); + if (!repositories.isEmpty()) { + popupGroup.add(new HgBranchPopupActions.BookmarkActions(myProject, repositories, branch)); + } + } + } + + @NotNull + protected DefaultActionGroup createRepositoriesActions() { + DefaultActionGroup popupGroup = new DefaultActionGroup(null, false); + popupGroup.addSeparator("Repositories"); + for (HgRepository repository : myRepositoryManager.getRepositories()) { + popupGroup.add(new RootAction<HgRepository>(repository, highlightCurrentRepo() ? myCurrentRepository : null, + new HgBranchPopupActions(repository.getProject(), repository).createActions(null), + HgUtil.getDisplayableBranchOrBookmarkText(repository))); + } + return popupGroup; + } + + protected void fillPopupWithCurrentRepositoryActions(@NotNull DefaultActionGroup popupGroup, @Nullable DefaultActionGroup actions) { + popupGroup.addAll(new HgBranchPopupActions(myProject, myCurrentRepository).createActions(actions)); + } +} + diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchPopupActions.java b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchPopupActions.java new file mode 100644 index 000000000000..10b97235f559 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchPopupActions.java @@ -0,0 +1,270 @@ +/* + * Copyright 2000-2013 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 org.zmlx.hg4idea.branch; + +import com.intellij.dvcs.DvcsUtil; +import com.intellij.dvcs.repo.Repository; +import com.intellij.dvcs.ui.NewBranchAction; +import com.intellij.openapi.actionSystem.ActionGroup; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DefaultActionGroup; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.project.DumbAwareAction; +import com.intellij.openapi.project.Project; +import com.intellij.util.ArrayUtil; +import com.intellij.util.Function; +import com.intellij.util.PlatformIcons; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.vcs.log.Hash; +import com.intellij.vcs.log.impl.HashImpl; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.zmlx.hg4idea.HgNameWithHashInfo; +import org.zmlx.hg4idea.HgRevisionNumber; +import org.zmlx.hg4idea.action.HgAbstractGlobalAction; +import org.zmlx.hg4idea.action.HgCommandResultNotifier; +import org.zmlx.hg4idea.command.HgBookmarkCommand; +import org.zmlx.hg4idea.command.HgBranchCreateCommand; +import org.zmlx.hg4idea.command.HgWorkingCopyRevisionsCommand; +import org.zmlx.hg4idea.execution.HgCommandException; +import org.zmlx.hg4idea.execution.HgCommandResult; +import org.zmlx.hg4idea.execution.HgCommandResultHandler; +import org.zmlx.hg4idea.repo.HgRepository; +import org.zmlx.hg4idea.ui.HgBookmarkDialog; +import org.zmlx.hg4idea.util.HgErrorUtil; + +import java.util.*; + +import static org.zmlx.hg4idea.util.HgUtil.getNamesWithoutHashes; +import static org.zmlx.hg4idea.util.HgUtil.getNewBranchNameFromUser; + +public class HgBranchPopupActions { + + private final Project myProject; + private final HgRepository myRepository; + + HgBranchPopupActions(Project project, HgRepository repository) { + myProject = project; + myRepository = repository; + } + + ActionGroup createActions(@Nullable DefaultActionGroup toInsert) { + DefaultActionGroup popupGroup = new DefaultActionGroup(null, false); + popupGroup.addAction(new HgNewBranchAction(myProject, Collections.singletonList(myRepository), myRepository)); + popupGroup.addAction(new HgNewBookmarkAction(myProject, Collections.singletonList(myRepository), myRepository)); + popupGroup.addAction(new HgShowUnnamedHeadsForCurrentBranchAction(myProject, myRepository)); + if (toInsert != null) { + popupGroup.addAll(toInsert); + } + + popupGroup.addSeparator("Bookmarks"); + List<String> bookmarkNames = getNamesWithoutHashes(myRepository.getBookmarks()); + String currentBookmark = myRepository.getCurrentBookmark(); + for (String bookmark : bookmarkNames) { + AnAction bookmarkAction = new BookmarkActions(myProject, Collections.singletonList(myRepository), bookmark); + if (bookmark.equals(currentBookmark)) { + bookmarkAction.getTemplatePresentation().setIcon(PlatformIcons.CHECK_ICON); + } + popupGroup.add(bookmarkAction); + } + + popupGroup.addSeparator("Branches"); + List<String> branchNamesList = new ArrayList<String>(myRepository.getOpenedBranches());//only opened branches have to be shown + Collections.sort(branchNamesList); + for (String branch : branchNamesList) { + if (!branch.equals(myRepository.getCurrentBranch())) { // don't show current branch in the list + popupGroup.add(new HgCommonBranchActions(myProject, Collections.singletonList(myRepository), branch)); + } + } + return popupGroup; + } + + public static class HgNewBranchAction extends NewBranchAction<HgRepository> { + @NotNull final HgRepository myPreselectedRepo; + + HgNewBranchAction(@NotNull Project project, @NotNull List<HgRepository> repositories, @NotNull HgRepository preselectedRepo) { + super(project, repositories); + myPreselectedRepo = preselectedRepo; + } + + @Override + public void actionPerformed(AnActionEvent e) { + final String name = getNewBranchNameFromUser(myPreselectedRepo, "Create New Branch"); + if (name == null) { + return; + } + for (final HgRepository repository : myRepositories) { + try { + new HgBranchCreateCommand(myProject, repository.getRoot(), name).execute(new HgCommandResultHandler() { + @Override + public void process(@Nullable HgCommandResult result) { + repository.update(); + if (HgErrorUtil.hasErrorsInCommandExecution(result)) { + new HgCommandResultNotifier(myProject) + .notifyError(result, "Creation failed", "Branch creation [" + name + "] failed"); + } + } + }); + } + catch (HgCommandException exception) { + HgAbstractGlobalAction.handleException(myProject, "Can't create new branch: ", exception); + } + } + } + } + + public static class HgNewBookmarkAction extends DumbAwareAction { + @NotNull protected final List<HgRepository> myRepositories; + @NotNull protected Project myProject; + @NotNull final HgRepository myPreselectedRepo; + + HgNewBookmarkAction(@NotNull Project project, @NotNull List<HgRepository> repositories, @NotNull HgRepository preselectedRepo) { + super("New Bookmark", "Create new bookmark", null); + myProject = project; + myRepositories = repositories; + myPreselectedRepo = preselectedRepo; + } + + @Override + public void update(AnActionEvent e) { + if (DvcsUtil.anyRepositoryIsFresh(myRepositories)) { + e.getPresentation().setEnabled(false); + e.getPresentation().setDescription("Bookmark creation is not possible before the first commit."); + } + } + + @Override + public void actionPerformed(AnActionEvent e) { + + final HgBookmarkDialog bookmarkDialog = new HgBookmarkDialog(myPreselectedRepo); + bookmarkDialog.show(); + if (bookmarkDialog.isOK()) { + final String name = bookmarkDialog.getName(); + for (HgRepository repository : myRepositories) { + try { + new HgBookmarkCommand(myProject, repository.getRoot(), name).createBookmark(bookmarkDialog.isActive()); + } + catch (HgCommandException exception) { + HgAbstractGlobalAction.handleException(myProject, exception); + } + } + } + } + } + + public static class HgShowUnnamedHeadsForCurrentBranchAction extends ActionGroup { + @NotNull final Project myProject; + @NotNull final HgRepository myRepository; + @NotNull final String myCurrentBranchName; + @NotNull Collection<Hash> myHeads = new HashSet<Hash>(); + + public HgShowUnnamedHeadsForCurrentBranchAction(@NotNull Project project, + @NotNull HgRepository repository) { + super(null, true); + myProject = project; + myRepository = repository; + myCurrentBranchName = repository.getCurrentBranch(); + getTemplatePresentation().setText(String.format("Unnamed heads for %s", myCurrentBranchName)); + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override + public void run() { + myHeads = filterUnnamedHeads(); + } + }); + } + + @NotNull + private Collection<Hash> filterUnnamedHeads() { + Collection<Hash> branchWithHashes = myRepository.getBranches().get(myCurrentBranchName); + if (branchWithHashes == null) { + // repository is fresh or branch is fresh. + return Collections.emptySet(); + } + else { + List<HgRevisionNumber> parents = new HgWorkingCopyRevisionsCommand(myProject).parents(myRepository.getRoot()); + if (parents.size() == 1) { + Collection<Hash> bookmarkHashes = ContainerUtil.map(myRepository.getBookmarks(), new Function<HgNameWithHashInfo, Hash>() { + + @Override + public Hash fun(HgNameWithHashInfo info) { + return info.getHash(); + } + }); + branchWithHashes.removeAll(bookmarkHashes); + branchWithHashes.remove(HashImpl.build(parents.get(0).getChangeset())); + } + } + return branchWithHashes; + } + + @NotNull + @Override + public AnAction[] getChildren(@Nullable AnActionEvent e) { + List<AnAction> branchHeadActions = new ArrayList<AnAction>(); + for (Hash hash : myHeads) { + branchHeadActions.add(new HgCommonBranchActions(myProject, Collections.singletonList(myRepository), hash.toShortString())); + } + return ContainerUtil.toArray(branchHeadActions, new AnAction[branchHeadActions.size()]); + } + + @Override + public void update(final AnActionEvent e) { + if (myRepository.isFresh()) { + e.getPresentation().setEnabled(false); + e.getPresentation().setDescription("Checkout of a new branch is not possible before the first commit."); + } + else if (!Repository.State.NORMAL.equals(myRepository.getState())) { + e.getPresentation().setEnabled(false); + } + } + } + + /** + * Actions available for bookmarks. + */ + static class BookmarkActions extends HgCommonBranchActions { + + BookmarkActions(@NotNull Project project, @NotNull List<HgRepository> repositories, @NotNull String branchName) { + super(project, repositories, branchName); + } + + @NotNull + @Override + public AnAction[] getChildren(@Nullable AnActionEvent e) { + return ArrayUtil.append(super.getChildren(e), new DeleteBookmarkAction(myProject, myRepositories, myBranchName)); + } + + private static class DeleteBookmarkAction extends HgBranchAbstractAction { + + DeleteBookmarkAction(@NotNull Project project, @NotNull List<HgRepository> repositories, @NotNull String branchName) { + super(project, "Delete", repositories, branchName); + } + + @Override + public void actionPerformed(AnActionEvent e) { + for (HgRepository repository : myRepositories) { + try { + new HgBookmarkCommand(myProject, repository.getRoot(), myBranchName).deleteBookmark(); + } + catch (HgCommandException exception) { + HgAbstractGlobalAction.handleException(myProject, exception); + } + } + } + } + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchUtil.java new file mode 100644 index 000000000000..9dbdd3ea7f65 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchUtil.java @@ -0,0 +1,77 @@ +/* + * 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. + */ +package org.zmlx.hg4idea.branch; + +import com.intellij.util.containers.ContainerUtil; +import com.intellij.vcs.log.Hash; +import org.jetbrains.annotations.NotNull; +import org.zmlx.hg4idea.HgNameWithHashInfo; +import org.zmlx.hg4idea.repo.HgRepository; +import org.zmlx.hg4idea.util.HgUtil; + +import java.util.*; + +public class HgBranchUtil { + + /** + * Only common hg heavy branches + */ + @NotNull + public static Collection<String> getCommonBranches(@NotNull Collection<HgRepository> repositories) { + Collection<String> commonBranches = null; + for (HgRepository repository : repositories) { + Map<String, Set<Hash>> branchesWithHashes = repository.getBranches(); + Collection<String> names = branchesWithHashes.keySet(); + if (commonBranches == null) { + commonBranches = names; + } + else { + commonBranches = ContainerUtil.intersection(commonBranches, names); + } + } + if (commonBranches != null) { + ArrayList<String> common = new ArrayList<String>(commonBranches); + Collections.sort(common); + return common; + } + else { + return Collections.emptyList(); + } + } + + @NotNull + public static Collection<String> getCommonBookmarks(@NotNull Collection<HgRepository> repositories) { + Collection<String> commonBookmarkNames = null; + for (HgRepository repository : repositories) { + Collection<HgNameWithHashInfo> bookmarksInfo = repository.getBookmarks(); + Collection<String> names = HgUtil.getNamesWithoutHashes(bookmarksInfo); + if (commonBookmarkNames == null) { + commonBookmarkNames = names; + } + else { + commonBookmarkNames = ContainerUtil.intersection(commonBookmarkNames, names); + } + } + if (commonBookmarkNames != null) { + ArrayList<String> common = new ArrayList<String>(commonBookmarkNames); + Collections.sort(common); + return common; + } + else { + return Collections.emptyList(); + } + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchesAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchesAction.java new file mode 100644 index 000000000000..b078da12548f --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchesAction.java @@ -0,0 +1,34 @@ +/* + * Copyright 2000-2013 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 org.zmlx.hg4idea.branch; + +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.zmlx.hg4idea.action.HgAbstractGlobalSingleRepoAction; +import org.zmlx.hg4idea.repo.HgRepository; + +import java.util.Collection; + +public class HgBranchesAction extends HgAbstractGlobalSingleRepoAction { + + @Override + protected void execute(@NotNull Project project, @NotNull Collection<HgRepository> repositories, @Nullable HgRepository selectedRepo) { + if (selectedRepo != null) { + HgBranchPopup.getInstance(project, selectedRepo).asListPopup().showInFocusCenter(); + } + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgCommonBranchActions.java b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgCommonBranchActions.java new file mode 100644 index 000000000000..ecba99f7b532 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgCommonBranchActions.java @@ -0,0 +1,141 @@ +/* + * 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. + */ +package org.zmlx.hg4idea.branch; + +import com.intellij.openapi.actionSystem.ActionGroup; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.VcsNotifier; +import com.intellij.openapi.vcs.update.UpdatedFiles; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.zmlx.hg4idea.HgVcs; +import org.zmlx.hg4idea.HgVcsMessages; +import org.zmlx.hg4idea.action.HgAbstractGlobalAction; +import org.zmlx.hg4idea.action.HgCommandResultNotifier; +import org.zmlx.hg4idea.command.HgMergeCommand; +import org.zmlx.hg4idea.command.HgUpdateCommand; +import org.zmlx.hg4idea.execution.HgCommandResult; +import org.zmlx.hg4idea.provider.update.HgConflictResolver; +import org.zmlx.hg4idea.provider.update.HgHeadMerger; +import org.zmlx.hg4idea.repo.HgRepository; +import org.zmlx.hg4idea.util.HgErrorUtil; + +import java.util.List; + +public class HgCommonBranchActions extends ActionGroup { + + @NotNull protected final Project myProject; + @NotNull protected String myBranchName; + @NotNull List<HgRepository> myRepositories; + + HgCommonBranchActions(@NotNull Project project, @NotNull List<HgRepository> repositories, @NotNull String branchName) { + super("", true); + myProject = project; + myBranchName = branchName; + myRepositories = repositories; + getTemplatePresentation().setText(myBranchName, false); // no mnemonics + } + + @NotNull + @Override + public AnAction[] getChildren(@Nullable AnActionEvent e) { + return new AnAction[]{ + new UpdateAction(myProject, myRepositories, myBranchName), + new MergeAction(myProject, myRepositories, myBranchName) + }; + } + + private static class MergeAction extends HgBranchAbstractAction { + + public MergeAction(@NotNull Project project, + @NotNull List<HgRepository> repositories, + @NotNull String branchName) { + super(project, "Merge", repositories, branchName); + } + + @Override + public void actionPerformed(AnActionEvent e) { + FileDocumentManager.getInstance().saveAllDocuments(); + final UpdatedFiles updatedFiles = UpdatedFiles.create(); + for (final HgRepository repository : myRepositories) { + final HgMergeCommand hgMergeCommand = new HgMergeCommand(myProject, repository.getRoot()); + hgMergeCommand.setRevision(myBranchName);//there is no difference between branch or revision or bookmark as parameter to merge, + // we need just a string + new Task.Backgroundable(myProject, "Merging changes...") { + @Override + public void run(@NotNull ProgressIndicator indicator) { + try { + new HgHeadMerger(myProject, hgMergeCommand) + .merge(repository.getRoot()); + new HgConflictResolver(myProject, updatedFiles).resolve(repository.getRoot()); + } + + catch (VcsException exception) { + assert myProject != null; // myProject couldn't be null, see annotation for Merge action + if (exception.isWarning()) { + VcsNotifier.getInstance(myProject).notifyWarning("Warning during merge", exception.getMessage()); + } + else { + VcsNotifier.getInstance(myProject).notifyError("Exception during merge", exception.getMessage()); + } + } + catch (Exception e1) { + HgAbstractGlobalAction.handleException(myProject, e1); + } + } + }.queue(); + } + } + } + + private static class UpdateAction extends HgBranchAbstractAction { + + public UpdateAction(@NotNull Project project, + @NotNull List<HgRepository> repositories, + @NotNull String branchName) { + super(project, "Update", repositories, branchName); + } + + @Override + public void actionPerformed(AnActionEvent e) { + FileDocumentManager.getInstance().saveAllDocuments(); + for (HgRepository repo : myRepositories) { + final VirtualFile repository = repo.getRoot(); + final HgUpdateCommand hgUpdateCommand = new HgUpdateCommand(myProject, repository); + hgUpdateCommand.setBranch(myBranchName); + new Task.Backgroundable(myProject, HgVcsMessages.message("action.hg4idea.updateTo.description", myBranchName)) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + HgCommandResult result = hgUpdateCommand.execute(); + assert myProject != null; // myProject couldn't be null, see annotation for updateTo action + if (HgErrorUtil.hasErrorsInCommandExecution(result)) { + new HgCommandResultNotifier(myProject).notifyError(result, "", "Update failed"); + new HgConflictResolver(myProject).resolve(repository); + } + myProject.getMessageBus().syncPublisher(HgVcs.BRANCH_TOPIC).update(myProject, repository); + } + }.queue(); + } + } + } +}
\ No newline at end of file diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgMultiRootBranchConfig.java b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgMultiRootBranchConfig.java new file mode 100644 index 000000000000..e762fb8992ab --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgMultiRootBranchConfig.java @@ -0,0 +1,50 @@ +/* + * 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. + */ +package org.zmlx.hg4idea.branch; + +import com.intellij.dvcs.branch.DvcsMultiRootBranchConfig; +import org.jetbrains.annotations.NotNull; +import org.zmlx.hg4idea.repo.HgRepository; + +import java.util.Collection; + +public class HgMultiRootBranchConfig extends DvcsMultiRootBranchConfig<HgRepository> { + + public HgMultiRootBranchConfig(@NotNull Collection<HgRepository> repositories) { + super(repositories); + } + + @NotNull + @Override + public Collection<String> getLocalBranchNames() { + return HgBranchUtil.getCommonBranches(myRepositories); + } + + @NotNull + Collection<String> getBookmarkNames() { + return HgBranchUtil.getCommonBookmarks(myRepositories); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + for (HgRepository repository : myRepositories) { + sb.append(repository.getPresentableUrl()).append(":").append(repository.getCurrentBranchName()).append(":") + .append(repository.getState()); + } + return sb.toString(); + } +} |