diff options
Diffstat (limited to 'plugins/hg4idea/src/org')
31 files changed, 901 insertions, 435 deletions
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgProjectSettings.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgProjectSettings.java index 936587d19755..8abac1bb0b1e 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgProjectSettings.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgProjectSettings.java @@ -12,6 +12,8 @@ // limitations under the License. package org.zmlx.hg4idea; +import com.intellij.dvcs.branch.DvcsBranchSync; +import com.intellij.dvcs.branch.DvcsSyncBranchSettings; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; @@ -24,7 +26,7 @@ import org.jetbrains.annotations.NotNull; name = "hg4idea.settings", storages = @Storage(file = StoragePathMacros.WORKSPACE_FILE) ) -public class HgProjectSettings implements PersistentStateComponent<HgProjectSettings.State> { +public class HgProjectSettings implements PersistentStateComponent<HgProjectSettings.State>, DvcsSyncBranchSettings { @NotNull private final HgGlobalSettings myAppSettings; @NotNull private final Project myProject; @@ -37,10 +39,12 @@ public class HgProjectSettings implements PersistentStateComponent<HgProjectSett } public static class State { + public boolean myCheckIncoming = true; public boolean myCheckOutgoing = true; public Boolean CHECK_INCOMING_OUTGOING = null; public boolean myIgnoreWhitespacesInAnnotations = true; + public DvcsBranchSync SYNC_SETTING = DvcsBranchSync.NOT_DECIDED; } public State getState() { @@ -62,6 +66,15 @@ public class HgProjectSettings implements PersistentStateComponent<HgProjectSett return myState.myIgnoreWhitespacesInAnnotations; } + @NotNull + public DvcsBranchSync getSyncSetting() { + return myState.SYNC_SETTING; + } + + public void setSyncSetting(@NotNull DvcsBranchSync syncSetting) { + myState.SYNC_SETTING = syncSetting; + } + public void setCheckIncomingOutgoing(boolean checkIncomingOutgoing) { myState.CHECK_INCOMING_OUTGOING = checkIncomingOutgoing; } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java index d6282ebe8786..8a521202aa3c 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java @@ -34,7 +34,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -abstract class HgAbstractGlobalAction extends AnAction { +public abstract class HgAbstractGlobalAction extends AnAction { protected HgAbstractGlobalAction(Icon icon) { super(icon); } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopup.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopup.java deleted file mode 100644 index c31e14e348d8..000000000000 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopup.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 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.action; - -import com.intellij.dvcs.DvcsUtil; -import com.intellij.dvcs.ui.BranchActionGroupPopup; -import com.intellij.dvcs.ui.RootAction; -import com.intellij.openapi.actionSystem.ActionGroup; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.DefaultActionGroup; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.popup.ListPopup; -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.ui.popup.list.ListPopupImpl; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.zmlx.hg4idea.repo.HgRepository; -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> - * - * @author NadyaZabrodina - */ -public class HgBranchPopup { - - private final Project myProject; - - private final HgRepository myCurrentRepository; - private final ListPopupImpl myPopup; - - public ListPopup asListPopup() { - return myPopup; - } - - /** - * @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) { - return new HgBranchPopup(project, currentRepository); - } - - private HgBranchPopup(@NotNull Project project, @NotNull HgRepository currentRepository) { - myProject = project; - myCurrentRepository = currentRepository; - String title = createPopupTitle(currentRepository); - - Condition<AnAction> preselectActionCondition = new Condition<AnAction>() { - @Override - public boolean value(AnAction action) { - return false; - } - }; - myPopup = new BranchActionGroupPopup(title, project, preselectActionCondition, createActions()); - setCurrentBranchInfo(); - } - - - @NotNull - private static String createPopupTitle(@NotNull HgRepository currentRepository) { - String title = "Hg Branches"; - title += " in " + DvcsUtil.getShortRepositoryName(currentRepository); - return title; - } - - private void setCurrentBranchInfo() { - String branchText = "Current branch : "; - //always display heavy branch name for additional info // - myPopup.setAdText(branchText + myCurrentRepository.getCurrentBranch(), SwingConstants.CENTER); - } - - - private ActionGroup createActions() { - DefaultActionGroup popupGroup = new DefaultActionGroup(null, false); - fillPopupWithCurrentRepositoryActions(popupGroup, createRepositoriesActions()); - popupGroup.addSeparator(); - return popupGroup; - } - - - @Nullable - private DefaultActionGroup createRepositoriesActions() { - List<VirtualFile> repositories = HgUtil.getHgRepositories(myProject); - if (repositories.size() == 1) { - return null; // if project has only one repository all branches, bookmarks and actions should be inline and no repository group needed - } - DefaultActionGroup popupGroup = new DefaultActionGroup(null, false); - popupGroup.addSeparator("Repositories"); - boolean isMultiRepoConfig = repositories.size() > 1; - for (VirtualFile repository : repositories) { - HgRepository repo = HgUtil.getRepositoryManager(myProject).getRepositoryForRoot(repository); - if (repo != null) { - popupGroup.add(new RootAction<HgRepository>(repo, isMultiRepoConfig ? myCurrentRepository : null, - new HgBranchPopupActions(repo.getProject(), repo).createActions(null), - HgUtil.getDisplayableBranchOrBookmarkText(repo))); - } - } - 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/action/HgCommonBranchActions.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCommonBranchActions.java deleted file mode 100644 index c79ae1ca0b7c..000000000000 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCommonBranchActions.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * 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.action; - -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.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; - -public class HgCommonBranchActions extends ActionGroup { - - @NotNull protected final Project myProject; - @NotNull protected String myBranchName; - @NotNull protected final HgRepository mySelectedRepository; - - HgCommonBranchActions(@NotNull Project project, @NotNull HgRepository selectedRepository, @NotNull String branchName) { - super("", true); - myProject = project; - myBranchName = branchName; - mySelectedRepository = selectedRepository; - getTemplatePresentation().setText(myBranchName, false); // no mnemonics - } - - @NotNull - @Override - public AnAction[] getChildren(@Nullable AnActionEvent e) { - return new AnAction[]{ - new UpdateAction(myProject, mySelectedRepository, myBranchName), - new MergeAction(myProject, mySelectedRepository, myBranchName) - }; - } - - private static class MergeAction extends HgBranchAbstractAction { - - public MergeAction(@NotNull Project project, - @NotNull HgRepository selectedRepository, - @NotNull String branchName) { - super(project, "Merge", selectedRepository, branchName); - } - - @Override - public void actionPerformed(AnActionEvent e) { - FileDocumentManager.getInstance().saveAllDocuments(); - final UpdatedFiles updatedFiles = UpdatedFiles.create(); - final HgMergeCommand hgMergeCommand = new HgMergeCommand(myProject, mySelectedRepository.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(mySelectedRepository.getRoot()); - new HgConflictResolver(myProject, updatedFiles).resolve(mySelectedRepository.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 HgRepository selectedRepository, - @NotNull String branchName) { - super(project, "Update", selectedRepository, branchName); - } - - @Override - public void actionPerformed(AnActionEvent e) { - final VirtualFile repository = mySelectedRepository.getRoot(); - FileDocumentManager.getInstance().saveAllDocuments(); - 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, null); - } - }.queue(); - } - } -}
\ No newline at end of file diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchAbstractAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchAbstractAction.java index 78b67013ed54..3998dedd0cc5 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchAbstractAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchAbstractAction.java @@ -13,24 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.zmlx.hg4idea.action; +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 HgRepository mySelectedRepository; + @NotNull protected final List<HgRepository> myRepositories; @NotNull protected final String myBranchName; public HgBranchAbstractAction(@NotNull Project project, @NotNull String title, - @NotNull HgRepository selectedRepository, + @NotNull List<HgRepository> repositories, @NotNull String branchName) { super(title); myProject = project; - mySelectedRepository = selectedRepository; + 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/action/HgBranchPopupActions.java b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchPopupActions.java index 45dd12bd9c81..10b97235f559 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopupActions.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchPopupActions.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.zmlx.hg4idea.action; +package org.zmlx.hg4idea.branch; import com.intellij.dvcs.DvcsUtil; import com.intellij.dvcs.repo.Repository; @@ -35,6 +35,8 @@ 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; @@ -73,7 +75,7 @@ public class HgBranchPopupActions { List<String> bookmarkNames = getNamesWithoutHashes(myRepository.getBookmarks()); String currentBookmark = myRepository.getCurrentBookmark(); for (String bookmark : bookmarkNames) { - AnAction bookmarkAction = new BookmarkActions(myProject, myRepository, bookmark); + AnAction bookmarkAction = new BookmarkActions(myProject, Collections.singletonList(myRepository), bookmark); if (bookmark.equals(currentBookmark)) { bookmarkAction.getTemplatePresentation().setIcon(PlatformIcons.CHECK_ICON); } @@ -85,13 +87,13 @@ public class HgBranchPopupActions { 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, myRepository, branch)); + popupGroup.add(new HgCommonBranchActions(myProject, Collections.singletonList(myRepository), branch)); } } return popupGroup; } - private static class HgNewBranchAction extends NewBranchAction<HgRepository> { + public static class HgNewBranchAction extends NewBranchAction<HgRepository> { @NotNull final HgRepository myPreselectedRepo; HgNewBranchAction(@NotNull Project project, @NotNull List<HgRepository> repositories, @NotNull HgRepository preselectedRepo) { @@ -105,25 +107,27 @@ public class HgBranchPopupActions { if (name == null) { return; } - try { - new HgBranchCreateCommand(myProject, myPreselectedRepo.getRoot(), name).execute(new HgCommandResultHandler() { - @Override - public void process(@Nullable HgCommandResult result) { - myPreselectedRepo.update(); - if (HgErrorUtil.hasErrorsInCommandExecution(result)) { - new HgCommandResultNotifier(myProject) - .notifyError(result, "Creation failed", "Branch creation [" + name + "] failed"); + 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); + }); + } + catch (HgCommandException exception) { + HgAbstractGlobalAction.handleException(myProject, "Can't create new branch: ", exception); + } } } } - private static class HgNewBookmarkAction extends DumbAwareAction { + public static class HgNewBookmarkAction extends DumbAwareAction { @NotNull protected final List<HgRepository> myRepositories; @NotNull protected Project myProject; @NotNull final HgRepository myPreselectedRepo; @@ -149,18 +153,20 @@ public class HgBranchPopupActions { final HgBookmarkDialog bookmarkDialog = new HgBookmarkDialog(myPreselectedRepo); bookmarkDialog.show(); if (bookmarkDialog.isOK()) { - try { - final String name = bookmarkDialog.getName(); - new HgBookmarkCommand(myProject, myPreselectedRepo.getRoot(), name).createBookmark(bookmarkDialog.isActive()); - } - catch (HgCommandException exception) { - HgAbstractGlobalAction.handleException(myProject, exception); + 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); + } } } } } - static private class HgShowUnnamedHeadsForCurrentBranchAction extends ActionGroup { + public static class HgShowUnnamedHeadsForCurrentBranchAction extends ActionGroup { @NotNull final Project myProject; @NotNull final HgRepository myRepository; @NotNull final String myCurrentBranchName; @@ -210,7 +216,7 @@ public class HgBranchPopupActions { public AnAction[] getChildren(@Nullable AnActionEvent e) { List<AnAction> branchHeadActions = new ArrayList<AnAction>(); for (Hash hash : myHeads) { - branchHeadActions.add(new HgCommonBranchActions(myProject, myRepository, hash.toShortString())); + branchHeadActions.add(new HgCommonBranchActions(myProject, Collections.singletonList(myRepository), hash.toShortString())); } return ContainerUtil.toArray(branchHeadActions, new AnAction[branchHeadActions.size()]); } @@ -232,29 +238,31 @@ public class HgBranchPopupActions { */ static class BookmarkActions extends HgCommonBranchActions { - BookmarkActions(@NotNull Project project, @NotNull HgRepository selectedRepository, @NotNull String branchName) { - super(project, selectedRepository, branchName); + 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, mySelectedRepository, myBranchName)); + return ArrayUtil.append(super.getChildren(e), new DeleteBookmarkAction(myProject, myRepositories, myBranchName)); } private static class DeleteBookmarkAction extends HgBranchAbstractAction { - DeleteBookmarkAction(@NotNull Project project, @NotNull HgRepository selectedRepository, @NotNull String branchName) { - super(project, "Delete", selectedRepository, branchName); + DeleteBookmarkAction(@NotNull Project project, @NotNull List<HgRepository> repositories, @NotNull String branchName) { + super(project, "Delete", repositories, branchName); } @Override public void actionPerformed(AnActionEvent e) { - try { - new HgBookmarkCommand(myProject, mySelectedRepository.getRoot(), myBranchName).deleteBookmark(); - } - catch (HgCommandException exception) { - HgAbstractGlobalAction.handleException(myProject, exception); + 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/action/HgBranchesAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchesAction.java index d799cde1705c..b078da12548f 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchesAction.java @@ -13,11 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.zmlx.hg4idea.action; +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; 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(); + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommitCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommitCommand.java index 5aa632e0a4ea..794c7096d207 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommitCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommitCommand.java @@ -53,6 +53,7 @@ public class HgCommitCommand { private final boolean myAmend; private Set<HgFile> myFiles = Collections.emptySet(); + @NotNull private List<String> mySubrepos = Collections.emptyList(); public HgCommitCommand(Project project, @NotNull VirtualFile root, String message, boolean amend) { myProject = project; @@ -70,6 +71,10 @@ public class HgCommitCommand { myFiles = files; } + public void setSubrepos(@NotNull List<String> subrepos) { + mySubrepos = subrepos; + } + public void execute() throws HgCommandException, VcsException { if (StringUtil.isEmptyOrSpaces(myMessage)) { throw new HgCommandException(HgVcsMessages.message("hg4idea.commit.error.messageEmpty")); @@ -88,7 +93,8 @@ public class HgCommitCommand { }); List<List<String>> chunkedCommits = VcsFileUtil.chunkRelativePaths(relativePaths); int size = chunkedCommits.size(); - commitChunkFiles(chunkedCommits.get(0), myAmend); + // commit with subrepo should be first, because it's not possible to amend with --subrepos argument; + commitChunkFiles(chunkedCommits.get(0), myAmend, !mySubrepos.isEmpty()); HgVcs vcs = HgVcs.getInstance(myProject); boolean amendCommit = vcs != null && vcs.getVersion().isAmendSupported(); for (int i = 1; i < size; i++) { @@ -105,14 +111,23 @@ public class HgCommitCommand { messageBus.syncPublisher(HgVcs.BRANCH_TOPIC).update(myProject, null); } - private void commitChunkFiles(List<String> chunk, boolean amendCommit) throws VcsException { + private void commitChunkFiles(@NotNull List<String> chunk, boolean amendCommit) throws VcsException { + commitChunkFiles(chunk, amendCommit, false); + } + + private void commitChunkFiles(@NotNull List<String> chunk, boolean amendCommit, boolean withSubrepos) throws VcsException { List<String> parameters = new LinkedList<String>(); parameters.add("--logfile"); parameters.add(saveCommitMessage().getAbsolutePath()); - parameters.addAll(chunk); - if (amendCommit) { + // note: for now mercurial could not perform amend commit with -S option + if (withSubrepos) { + parameters.add("-S"); + parameters.addAll(mySubrepos); + } + else if (amendCommit) { parameters.add("--amend"); } + parameters.addAll(chunk); HgCommandExecutor executor = new HgCommandExecutor(myProject); executor.setCharset(myCharset); ensureSuccess(executor.executeInCurrentThread(myRoot, "commit", parameters)); @@ -129,5 +144,4 @@ public class HgCommitCommand { } return tempFile; } - } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandExecutor.java b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandExecutor.java index 7cf8f65559ea..f27d6a0d6550 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandExecutor.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandExecutor.java @@ -49,7 +49,7 @@ import java.util.List; */ public class HgCommandExecutor { - protected static final Logger LOG = Logger.getInstance(HgRemoteCommandExecutor.class.getName()); + protected static final Logger LOG = Logger.getInstance(HgCommandExecutor.class.getName()); private static final List<String> DEFAULT_OPTIONS = Arrays.asList("--config", "ui.merge=internal:merge"); protected final Project myProject; diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java index de565484e2d5..2d3a7bce191b 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java @@ -54,9 +54,9 @@ public class HgHistoryUtil { } @NotNull - public static List<? extends VcsCommitMetadata> loadMetadata(@NotNull final Project project, - @NotNull final VirtualFile root, int limit, - @NotNull List<String> parameters) throws VcsException { + public static List<VcsCommitMetadata> loadMetadata(@NotNull final Project project, + @NotNull final VirtualFile root, int limit, + @NotNull List<String> parameters) throws VcsException { final VcsLogObjectsFactory factory = getObjectsFactoryWithDisposeCheck(project); if (factory == null) { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java index 3b989e448b61..109e83899e5b 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java @@ -22,9 +22,11 @@ import com.intellij.openapi.util.Couple; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.VcsKey; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.CollectConsumer; import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import com.intellij.vcs.log.*; +import com.intellij.vcs.log.impl.LogDataImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.zmlx.hg4idea.HgNameWithHashInfo; @@ -59,18 +61,23 @@ public class HgLogProvider implements VcsLogProvider { @NotNull @Override - public List<? extends VcsCommitMetadata> readFirstBlock(@NotNull VirtualFile root, - @NotNull Requirements requirements) throws VcsException { - return HgHistoryUtil.loadMetadata(myProject, root, requirements.getCommitCount(), Collections.<String>emptyList()); + public DetailedLogData readFirstBlock(@NotNull VirtualFile root, + @NotNull Requirements requirements) throws VcsException { + List<VcsCommitMetadata> commits = HgHistoryUtil.loadMetadata(myProject, root, requirements.getCommitCount(), + Collections.<String>emptyList()); + return new LogDataImpl(readAllRefs(root), commits); } @Override - public void readAllHashes(@NotNull VirtualFile root, @NotNull Consumer<VcsUser> userRegistry, - @NotNull Consumer<TimedVcsCommit> commitConsumer) throws VcsException { - List<TimedVcsCommit> commits = HgHistoryUtil.readAllHashes(myProject, root, userRegistry, Collections.<String>emptyList()); + @NotNull + public LogData readAllHashes(@NotNull VirtualFile root, @NotNull final Consumer<TimedVcsCommit> commitConsumer) throws VcsException { + Set<VcsUser> userRegistry = ContainerUtil.newHashSet(); + List<TimedVcsCommit> commits = HgHistoryUtil.readAllHashes(myProject, root, new CollectConsumer<VcsUser>(userRegistry), + Collections.<String>emptyList()); for (TimedVcsCommit commit : commits) { commitConsumer.consume(commit); } + return new LogDataImpl(readAllRefs(root), userRegistry); } @NotNull @@ -87,16 +94,15 @@ public class HgLogProvider implements VcsLogProvider { } @NotNull - @Override - public Collection<VcsRef> readAllRefs(@NotNull VirtualFile root) throws VcsException { + private Set<VcsRef> readAllRefs(@NotNull VirtualFile root) throws VcsException { myRepositoryManager.waitUntilInitialized(); if (myProject.isDisposed()) { - return Collections.emptyList(); + return Collections.emptySet(); } HgRepository repository = myRepositoryManager.getRepositoryForRoot(root); if (repository == null) { LOG.error("Repository not found for root " + root); - return Collections.emptyList(); + return Collections.emptySet(); } repository.update(); @@ -106,7 +112,7 @@ public class HgLogProvider implements VcsLogProvider { Collection<HgNameWithHashInfo> tags = repository.getTags(); Collection<HgNameWithHashInfo> localTags = repository.getLocalTags(); - Collection<VcsRef> refs = new ArrayList<VcsRef>(branches.size() + bookmarks.size()); + Set<VcsRef> refs = new HashSet<VcsRef>(branches.size() + bookmarks.size()); for (Map.Entry<String, Set<Hash>> entry : branches.entrySet()) { String branchName = entry.getKey(); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java index 02e49354f3ab..14a288171504 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java @@ -17,19 +17,24 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.JBColor; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.zmlx.hg4idea.*; import org.zmlx.hg4idea.command.HgResolveCommand; import org.zmlx.hg4idea.command.HgResolveStatusEnum; import org.zmlx.hg4idea.command.HgStatusCommand; import org.zmlx.hg4idea.command.HgWorkingCopyRevisionsCommand; +import org.zmlx.hg4idea.repo.HgRepository; import org.zmlx.hg4idea.util.HgUtil; -import java.awt.*; +import java.io.File; import java.util.*; -import java.util.List; public class HgChangeProvider implements ChangeProvider { @@ -38,7 +43,7 @@ public class HgChangeProvider implements ChangeProvider { public static final FileStatus COPIED = FileStatusFactory.getInstance().createFileStatus("COPIED", "Copied", FileStatus.COLOR_ADDED); public static final FileStatus RENAMED = FileStatusFactory.getInstance().createFileStatus("RENAMED", "Renamed", - Color.cyan.darker().darker()); + JBColor.CYAN.darker().darker()); private static final EnumMap<HgFileStatusEnum, HgChangeProcessor> PROCESSORS = new EnumMap<HgFileStatusEnum, HgChangeProcessor>(HgFileStatusEnum.class); @@ -85,21 +90,42 @@ public class HgChangeProvider implements ChangeProvider { final Map<HgFile, HgResolveStatusEnum> list = new HgResolveCommand(myProject).getListSynchronously(repo); hgChanges.addAll(new HgStatusCommand.Builder(true).build(myProject).execute(repo, entry.getValue())); + final HgRepository hgRepo = HgUtil.getRepositoryForFile(myProject, repo); + if (hgRepo != null && hgRepo.hasSubrepos()) { + hgChanges.addAll(ContainerUtil.mapNotNull(hgRepo.getSubrepos(), new Function<HgNameWithHashInfo, HgChange>() { + @Override + public HgChange fun(HgNameWithHashInfo info) { + return findChange(hgRepo, info); + } + })); + } + sendChanges(builder, hgChanges, list, workingRevision, parentRevision); } return hgChanges; } + @Nullable + private HgChange findChange(@NotNull HgRepository hgRepo, @NotNull HgNameWithHashInfo info) { + File file = new File(hgRepo.getRoot().getPath(), info.getName()); + VirtualFile virtualSubrepoFile = VfsUtil.findFileByIoFile(file, false); + HgRepository subrepo = HgUtil.getRepositoryForFile(myProject, virtualSubrepoFile); + if (subrepo != null && !info.getHash().asString().equals(subrepo.getCurrentRevision())) { + return new HgChange(new HgFile(hgRepo.getRoot(), new FilePathImpl(virtualSubrepoFile)), HgFileStatusEnum.MODIFIED); + } + return null; + } + private void sendChanges(ChangelistBuilder builder, Set<HgChange> changes, - Map<HgFile, HgResolveStatusEnum> resolveStatus, HgRevisionNumber workingRevision, - HgRevisionNumber parentRevision) { + Map<HgFile, HgResolveStatusEnum> resolveStatus, HgRevisionNumber workingRevision, + HgRevisionNumber parentRevision) { for (HgChange change : changes) { HgFile afterFile = change.afterFile(); HgFile beforeFile = change.beforeFile(); HgFileStatusEnum status = change.getStatus(); if (resolveStatus.containsKey(afterFile) - && resolveStatus.get(afterFile) == HgResolveStatusEnum.UNRESOLVED) { + && resolveStatus.get(afterFile) == HgResolveStatusEnum.UNRESOLVED) { builder.processChange( new Change( new HgContentRevision(myProject, beforeFile, parentRevision), @@ -286,9 +312,9 @@ public class HgChangeProvider implements ChangeProvider { HgFile afterFile ); - final void processChange(ContentRevision contentRevisionBefore, - ContentRevision contentRevisionAfter, FileStatus fileStatus, - ChangelistBuilder builder, VcsKey vcsKey) { + static void processChange(ContentRevision contentRevisionBefore, + ContentRevision contentRevisionAfter, FileStatus fileStatus, + ChangelistBuilder builder, VcsKey vcsKey) { if (contentRevisionBefore == null && contentRevisionAfter == null) { return; } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCurrentBinaryContentRevision.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCurrentBinaryContentRevision.java index 8be5a7b0a9dd..a11a6c54e0c2 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCurrentBinaryContentRevision.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCurrentBinaryContentRevision.java @@ -14,20 +14,28 @@ package org.zmlx.hg4idea.provider; import com.intellij.openapi.vcs.changes.CurrentBinaryContentRevision; import com.intellij.openapi.vcs.history.VcsRevisionNumber; +import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.zmlx.hg4idea.HgFile; -final class HgCurrentBinaryContentRevision extends CurrentBinaryContentRevision { - private VcsRevisionNumber revisionNumber; +final public class HgCurrentBinaryContentRevision extends CurrentBinaryContentRevision { + @NotNull private VcsRevisionNumber myRevisionNumber; + @NotNull private VirtualFile myRepositoryRoot; - HgCurrentBinaryContentRevision(HgFile hgFile, VcsRevisionNumber revisionNumber) { + HgCurrentBinaryContentRevision(@NotNull HgFile hgFile, @NotNull VcsRevisionNumber revisionNumber) { super(hgFile.toFilePath()); - this.revisionNumber = revisionNumber; + myRepositoryRoot = hgFile.getRepo(); + myRevisionNumber = revisionNumber; } @NotNull @Override public VcsRevisionNumber getRevisionNumber() { - return revisionNumber; + return myRevisionNumber; + } + + @NotNull + public VirtualFile getRepositoryRoot() { + return myRepositoryRoot; } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCurrentContentRevision.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCurrentContentRevision.java index c6c4bf72710b..3c427d8d7db9 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCurrentContentRevision.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCurrentContentRevision.java @@ -34,7 +34,7 @@ class HgCurrentContentRevision extends CurrentContentRevision { return revisionNumber; } - public static ContentRevision create(@NotNull HgFile hgFile, HgRevisionNumber revision) { + public static ContentRevision create(@NotNull HgFile hgFile, @NotNull HgRevisionNumber revision) { VirtualFile virtualFile = VcsUtil.getVirtualFile(hgFile.getFile()); if (virtualFile == null) { return null; diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java index 06b74148156e..509e4f82eaff 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java @@ -20,21 +20,21 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.vcs.CheckinProjectPanel; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.changes.ChangeList; -import com.intellij.openapi.vcs.changes.ContentRevision; -import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; +import com.intellij.openapi.vcs.changes.*; import com.intellij.openapi.vcs.checkin.CheckinEnvironment; import com.intellij.openapi.vcs.ui.RefreshableOnComponent; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.FunctionUtil; import com.intellij.util.NullableFunction; import com.intellij.util.PairConsumer; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; import com.intellij.vcsUtil.VcsUtil; +import com.intellij.xml.util.XmlStringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.zmlx.hg4idea.*; @@ -43,17 +43,23 @@ import org.zmlx.hg4idea.command.*; import org.zmlx.hg4idea.execution.HgCommandException; import org.zmlx.hg4idea.execution.HgCommandExecutor; import org.zmlx.hg4idea.execution.HgCommandResult; +import org.zmlx.hg4idea.provider.HgCurrentBinaryContentRevision; import org.zmlx.hg4idea.repo.HgRepository; -import org.zmlx.hg4idea.repo.HgRepositoryManager; import org.zmlx.hg4idea.util.HgUtil; +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.util.*; +import java.util.List; public class HgCheckinEnvironment implements CheckinEnvironment { private final Project myProject; private boolean myNextCommitIsPushed; private boolean myNextCommitAmend; // If true, the next commit is amended + private boolean myShouldCommitSubrepos; public HgCheckinEnvironment(Project project) { myProject = project; @@ -83,21 +89,21 @@ public class HgCheckinEnvironment implements CheckinEnvironment { @NotNull NullableFunction<Object, Object> parametersHolder, Set<String> feedback) { List<VcsException> exceptions = new LinkedList<VcsException>(); - Map<VirtualFile, Set<HgFile>> repositoriesMap = getFilesByRepository(changes); - for (Map.Entry<VirtualFile, Set<HgFile>> entry : repositoriesMap.entrySet()) { + Map<HgRepository, Set<HgFile>> repositoriesMap = getFilesByRepository(changes); + for (Map.Entry<HgRepository, Set<HgFile>> entry : repositoriesMap.entrySet()) { - VirtualFile repo = entry.getKey(); + HgRepository repo = entry.getKey(); Set<HgFile> selectedFiles = entry.getValue(); + HgCommitCommand command = + new HgCommitCommand(myProject, repo.getRoot(), preparedComment, myNextCommitAmend); - HgCommitCommand command = new HgCommitCommand(myProject, repo, preparedComment, myNextCommitAmend); - - if (isMergeCommit(repo)) { + if (isMergeCommit(repo.getRoot())) { //partial commits are not allowed during merges //verifyResult that all changed files in the repo are selected //If so, commit the entire repository //If not, abort - Set<HgFile> changedFilesNotInCommit = getChangedFilesNotInCommit(repo, selectedFiles); + Set<HgFile> changedFilesNotInCommit = getChangedFilesNotInCommit(repo.getRoot(), selectedFiles); boolean partial = !changedFilesNotInCommit.isEmpty(); @@ -122,6 +128,9 @@ public class HgCheckinEnvironment implements CheckinEnvironment { // so no need to set the files on the command, because then mercurial will complain } else { command.setFiles(selectedFiles); + if (myShouldCommitSubrepos && repo.hasSubrepos()) { + command.setSubrepos(HgUtil.getNamesWithoutHashes(repo.getSubrepos())); + } } try { command.execute(); @@ -134,9 +143,7 @@ public class HgCheckinEnvironment implements CheckinEnvironment { // push if needed if (myNextCommitIsPushed && exceptions.isEmpty()) { - final Set<VirtualFile> preselectedFiles = repositoriesMap.keySet(); - HgRepositoryManager repositoryManager = HgUtil.getRepositoryManager(myProject); - final List<HgRepository> preselectedRepositories = HgActionUtil.collectRepositoriesFromFiles(repositoryManager, preselectedFiles); + final List<HgRepository> preselectedRepositories = ContainerUtil.newArrayList(repositoriesMap.keySet()); UIUtil.invokeLaterIfNeeded(new Runnable() { public void run() { new VcsPushDialog(myProject, preselectedRepositories).show(); @@ -154,7 +161,8 @@ public class HgCheckinEnvironment implements CheckinEnvironment { private Set<HgFile> getChangedFilesNotInCommit(VirtualFile repo, Set<HgFile> selectedFiles) { List<HgRevisionNumber> parents = new HgWorkingCopyRevisionsCommand(myProject).parents(repo); - HgStatusCommand statusCommand = new HgStatusCommand.Builder(true).unknown(false).ignored(false).baseRevision(parents.get(0)).build(myProject); + HgStatusCommand statusCommand = + new HgStatusCommand.Builder(true).unknown(false).ignored(false).baseRevision(parents.get(0)).build(myProject); Set<HgChange> allChangedFilesInRepo = statusCommand.execute(repo); Set<HgFile> filesNotIncluded = new HashSet<HgFile>(); @@ -229,29 +237,29 @@ public class HgCheckinEnvironment implements CheckinEnvironment { } @NotNull - private Map<VirtualFile, Set<HgFile>> getFilesByRepository(List<Change> changes) { - Map<VirtualFile, Set<HgFile>> result = new HashMap<VirtualFile, Set<HgFile>>(); + private Map<HgRepository, Set<HgFile>> getFilesByRepository(List<Change> changes) { + Map<HgRepository, Set<HgFile>> result = new HashMap<HgRepository, Set<HgFile>>(); for (Change change : changes) { ContentRevision afterRevision = change.getAfterRevision(); ContentRevision beforeRevision = change.getBeforeRevision(); if (afterRevision != null) { - addFile(result, afterRevision.getFile()); + addFile(result, afterRevision); } if (beforeRevision != null) { - addFile(result, beforeRevision.getFile()); + addFile(result, beforeRevision); } } return result; } - private void addFile(Map<VirtualFile, Set<HgFile>> result, FilePath filePath) { - if (filePath == null) { - return; - } - - VirtualFile repo = VcsUtil.getVcsRootFor(myProject, filePath); - if (repo == null || filePath.isDirectory()) { + private void addFile(Map<HgRepository, Set<HgFile>> result, ContentRevision contentRevision) { + FilePath filePath = contentRevision.getFile(); + // try to find repository from hgFile from change + HgRepository repo = HgUtil.getRepositoryForFile(myProject, contentRevision instanceof HgCurrentBinaryContentRevision + ? ((HgCurrentBinaryContentRevision)contentRevision).getRepositoryRoot() + : ChangesUtil.findValidParentAccurately(filePath)); + if (repo == null) { return; } @@ -261,7 +269,7 @@ public class HgCheckinEnvironment implements CheckinEnvironment { result.put(repo, hgFiles); } - hgFiles.add(new HgFile(repo, filePath)); + hgFiles.add(new HgFile(repo.getRoot(), filePath)); } public void setNextCommitIsPushed() { @@ -272,27 +280,55 @@ public class HgCheckinEnvironment implements CheckinEnvironment { * Commit options for hg */ private class HgCommitAdditionalComponent extends DvcsCommitAdditionalComponent { + @NotNull private final JCheckBox myCommitSubrepos; public HgCommitAdditionalComponent(@NotNull Project project, @NotNull CheckinProjectPanel panel) { super(project, panel); HgVcs myVcs = HgVcs.getInstance(myProject); myAmend.setEnabled(myVcs != null && myVcs.getVersion().isAmendSupported()); + final Insets insets = new Insets(2, 2, 2, 2); + // add commit subrepos checkbox + GridBagConstraints c = new GridBagConstraints(); + c.anchor = GridBagConstraints.CENTER; + c.insets = insets; + c.gridx = 1; + c.gridy = 2; + c.weightx = 1; + c.fill = GridBagConstraints.HORIZONTAL; + myCommitSubrepos = new JCheckBox("Commit subrepositories", false); + myCommitSubrepos.setToolTipText(XmlStringUtil.wrapInHtml( + "Commit all subrepos for selected repositories.<br>" + + " <code>hg ci <i><b>files</b></i> -S <i><b>subrepos</b></i></code>")); + myCommitSubrepos.setMnemonic('s'); + myPanel.add(myCommitSubrepos, c); + Collection<HgRepository> repos = + HgActionUtil.collectRepositoriesFromFiles(HgUtil.getRepositoryManager(myProject), myCheckinPanel.getRoots()); + myCommitSubrepos.setVisible(ContainerUtil.exists(repos, new Condition<HgRepository>() { + @Override + public boolean value(HgRepository repository) { + return repository.hasSubrepos(); + } + })); + myCommitSubrepos.addActionListener(new MySelectionListener(myAmend)); + myAmend.addActionListener(new MySelectionListener(myCommitSubrepos)); } @Override public void refresh() { super.refresh(); - myNextCommitAmend = false; + restoreState(); } @Override public void saveState() { myNextCommitAmend = myAmend.isSelected(); + myShouldCommitSubrepos = myCommitSubrepos.isSelected(); } @Override public void restoreState() { myNextCommitAmend = false; + myShouldCommitSubrepos = false; } @NotNull @@ -313,5 +349,25 @@ public class HgCheckinEnvironment implements CheckinEnvironment { HgCommandResult result = commandExecutor.executeInCurrentThread(repo, "log", args); return result == null ? "" : result.getRawOutput(); } + + private class MySelectionListener implements ActionListener { + JCheckBox myUnselectedComponent; + + public MySelectionListener(JCheckBox unselectedComponent) { + myUnselectedComponent = unselectedComponent; + } + + @Override + public void actionPerformed(ActionEvent e) { + JCheckBox source = (JCheckBox)e.getSource(); + if (source.isSelected()) { + myUnselectedComponent.setSelected(false); + myUnselectedComponent.setEnabled(false); + } + else{ + myUnselectedComponent.setEnabled(true); + } + } + } } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java index 13f4aaa08f6a..af584d52c32c 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java @@ -15,28 +15,19 @@ */ package org.zmlx.hg4idea.push; -import com.intellij.dvcs.DvcsUtil; import com.intellij.dvcs.push.*; import com.intellij.dvcs.repo.RepositoryManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.AbstractVcs; -import com.intellij.ui.SimpleColoredText; -import com.intellij.ui.SimpleTextAttributes; -import com.intellij.util.Function; import com.intellij.util.ObjectUtils; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.zmlx.hg4idea.HgVcs; import org.zmlx.hg4idea.repo.HgRepository; import org.zmlx.hg4idea.util.HgUtil; -import java.util.List; - public class HgPushSupport extends PushSupport<HgRepository, HgPushSource, HgTarget> { - private final static String ENTER_REMOTE = "Enter Remote"; @NotNull private final Project myProject; @NotNull private final HgVcs myVcs; @@ -72,28 +63,11 @@ public class HgPushSupport extends PushSupport<HgRepository, HgPushSource, HgTar @NotNull @Override - public List<String> getTargetNames(@NotNull HgRepository repository) { - return ContainerUtil.sorted(ContainerUtil.map(repository.getRepositoryConfig().getPaths(), new Function<String, String>() { - @Override - public String fun(String s) { - return HgUtil.removePasswordIfNeeded(s); - } - })); - } - - @NotNull - @Override public HgPushSource getSource(@NotNull HgRepository repository) { - String localBranch = HgUtil.getActiveBranchName(repository); + String localBranch = repository.getCurrentBranchName(); return new HgPushSource(localBranch); } - @Override - @NotNull - public HgTarget createTarget(@NotNull HgRepository repository, @NotNull String targetName) { - return new HgTarget(targetName); - } - @NotNull @Override public RepositoryManager<HgRepository> getRepositoryManager() { @@ -106,18 +80,8 @@ public class HgPushSupport extends PushSupport<HgRepository, HgPushSource, HgTar } @Override - @Nullable - public VcsError validate(@NotNull HgRepository repository, @Nullable String targetToValidate) { - return StringUtil.isEmptyOrSpaces(targetToValidate) - ? VcsError.createEmptyTargetError(DvcsUtil.getShortRepositoryName(repository)) - : null; - } - - @Override - public SimpleColoredText renderTarget(@Nullable HgTarget target) { - if (target == null || StringUtil.isEmptyOrSpaces(target.getPresentation())) { - return new SimpleColoredText(ENTER_REMOTE, SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES); - } - return new SimpleColoredText(target.getPresentation(), SimpleTextAttributes.SYNTHETIC_ATTRIBUTES); + @NotNull + public PushTargetPanel<HgTarget> createTargetPanel(@NotNull HgRepository repository, @Nullable HgTarget defaultTarget) { + return new HgPushTargetPanel(repository, defaultTarget); } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushTargetPanel.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushTargetPanel.java new file mode 100644 index 000000000000..e3d02ea4e3fb --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushTargetPanel.java @@ -0,0 +1,88 @@ +/* + * 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.push; + +import com.intellij.dvcs.DvcsUtil; +import com.intellij.dvcs.push.PushTargetPanel; +import com.intellij.dvcs.push.VcsError; +import com.intellij.openapi.ui.ValidationInfo; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.ui.ColoredTreeCellRenderer; +import com.intellij.ui.SimpleTextAttributes; +import com.intellij.ui.TextFieldWithAutoCompletion; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.zmlx.hg4idea.repo.HgRepository; +import org.zmlx.hg4idea.util.HgUtil; + +import java.awt.*; +import java.util.List; + +public class HgPushTargetPanel extends PushTargetPanel<HgTarget> { + + private final static String ENTER_REMOTE = "Enter Remote"; + private final HgRepository myRepository; + private final TextFieldWithAutoCompletion<String> myDestTargetPanel; + private String myOldText; + + public HgPushTargetPanel(@NotNull HgRepository repository, @Nullable HgTarget defaultTarget) { + setLayout(new BorderLayout()); + setOpaque(false); + myRepository = repository; + final List<String> targetVariants = HgUtil.getTargetNames(repository); + myOldText = defaultTarget != null ? defaultTarget.getPresentation() : ""; + myDestTargetPanel = new PushTargetTextField(repository.getProject(), targetVariants, myOldText); + add(myDestTargetPanel, BorderLayout.CENTER); + } + + @Override + public void render(@NotNull ColoredTreeCellRenderer renderer) { + String targetText = myDestTargetPanel.getText(); + if (StringUtil.isEmptyOrSpaces(targetText)) { + renderer.append(ENTER_REMOTE, SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES, this); + } + renderer.append(targetText, SimpleTextAttributes.SYNTHETIC_ATTRIBUTES, this); + } + + @Override + @NotNull + public HgTarget getValue() { + return createValidPushTarget(); + } + + @NotNull + private HgTarget createValidPushTarget() { + return new HgTarget(myDestTargetPanel.getText()); + } + + @Override + public void fireOnCancel() { + myDestTargetPanel.setText(myOldText); + } + + @Override + public void fireOnChange() { + myOldText = myDestTargetPanel.getText(); + } + + @Nullable + public ValidationInfo verify() { + if (StringUtil.isEmptyOrSpaces(myDestTargetPanel.getText())) { + return new ValidationInfo(VcsError.createEmptyTargetError(DvcsUtil.getShortRepositoryName(myRepository)).getText(), this); + } + return null; + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgTarget.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgTarget.java index 8f5aca3838ca..87a5d3bf321e 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgTarget.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgTarget.java @@ -26,7 +26,6 @@ public class HgTarget implements PushTarget { myTarget = name; } - @Override @NotNull public String getPresentation() { return HgUtil.removePasswordIfNeeded(myTarget); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/PushTargetTextField.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/PushTargetTextField.java new file mode 100644 index 000000000000..c05cb9133121 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/PushTargetTextField.java @@ -0,0 +1,63 @@ +/* + * 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.push; + +import com.intellij.openapi.editor.ex.EditorEx; +import com.intellij.openapi.project.Project; +import com.intellij.ui.TextFieldWithAutoCompletion; +import com.intellij.ui.TextFieldWithAutoCompletionListProvider; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; + +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.util.List; + +public class PushTargetTextField extends TextFieldWithAutoCompletion<String> { + + public PushTargetTextField(@NotNull Project project, @NotNull final List<String> targetVariants, @NotNull String defaultTargetName) { + super(project, getCompletionProvider(targetVariants), true, defaultTargetName); + setBorder(UIUtil.getTableFocusCellHighlightBorder()); + setOneLineMode(true); + addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + selectAll(); + } + }); + } + + @Override + public boolean shouldHaveBorder() { + return false; + } + + @Override + protected void updateBorder(@NotNull final EditorEx editor) { + } + + @NotNull + private static TextFieldWithAutoCompletionListProvider<String> getCompletionProvider(@NotNull final List<String> targetVariants) { + return new StringsCompletionProvider(targetVariants, null) { + @Override + public int compare(String item1, String item2) { + return Integer.valueOf(ContainerUtil.indexOf(targetVariants, item1)).compareTo(ContainerUtil.indexOf(targetVariants, item2)); + } + }; + } + +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepoInfo.java b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepoInfo.java index f73375f9c791..55efa0b43418 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepoInfo.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepoInfo.java @@ -34,6 +34,7 @@ public class HgRepoInfo { @NotNull private Set<HgNameWithHashInfo> myBookmarks = Collections.emptySet(); @NotNull private Set<HgNameWithHashInfo> myTags = Collections.emptySet(); @NotNull private Set<HgNameWithHashInfo> myLocalTags = Collections.emptySet(); + @NotNull Set<HgNameWithHashInfo> mySubrepos = Collections.emptySet(); public HgRepoInfo(@NotNull String currentBranch, @Nullable String currentRevision, @@ -43,7 +44,7 @@ public class HgRepoInfo { @NotNull Collection<HgNameWithHashInfo> bookmarks, @Nullable String currentBookmark, @NotNull Collection<HgNameWithHashInfo> tags, - @NotNull Collection<HgNameWithHashInfo> localTags) { + @NotNull Collection<HgNameWithHashInfo> localTags, @NotNull Collection<HgNameWithHashInfo> subrepos) { myCurrentBranch = currentBranch; myCurrentRevision = currentRevision; myTipRevision = currentTipRevision; @@ -53,6 +54,7 @@ public class HgRepoInfo { myCurrentBookmark = currentBookmark; myTags = new LinkedHashSet<HgNameWithHashInfo>(tags); myLocalTags = new LinkedHashSet<HgNameWithHashInfo>(localTags); + mySubrepos = new HashSet<HgNameWithHashInfo>(subrepos); } @NotNull @@ -116,6 +118,7 @@ public class HgRepoInfo { if (!myBookmarks.equals(info.myBookmarks)) return false; if (!myTags.equals(info.myTags)) return false; if (!myLocalTags.equals(info.myLocalTags)) return false; + if (!mySubrepos.equals(info.mySubrepos)) return false; return true; } @@ -123,7 +126,7 @@ public class HgRepoInfo { @Override public int hashCode() { return Objects.hashCode(myCurrentBranch, myCurrentRevision, myTipRevision, myCurrentBookmark, myState, myBranches, myBookmarks, myTags, - myLocalTags); + myLocalTags, mySubrepos); } @Override @@ -132,4 +135,13 @@ public class HgRepoInfo { return String.format("HgRepository{myCurrentBranch=%s, myCurrentRevision='%s', myState=%s}", myCurrentBranch, myCurrentRevision, myState); } + + public boolean hasSubrepos() { + return !mySubrepos.isEmpty(); + } + + @NotNull + public Collection<HgNameWithHashInfo> getSubrepos() { + return mySubrepos; + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepository.java b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepository.java index 8a5c4fc81e53..8d3b66f0ba54 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepository.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepository.java @@ -71,5 +71,10 @@ public interface HgRepository extends Repository { @NotNull HgConfig getRepositoryConfig(); + boolean hasSubrepos(); + + @NotNull + Collection<HgNameWithHashInfo> getSubrepos(); + void updateConfig(); } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java index b670fb056c0c..6203f259b9bc 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java @@ -21,6 +21,7 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; @@ -99,6 +100,19 @@ public class HgRepositoryImpl extends RepositoryImpl implements HgRepository { @Nullable @Override + /** + * Return active bookmark name if exist or heavy branch name otherwise + */ + public String getCurrentBranchName() { + String branchOrBookMarkName = getCurrentBookmark(); + if (StringUtil.isEmptyOrSpaces(branchOrBookMarkName)) { + branchOrBookMarkName = getCurrentBranch(); + } + return branchOrBookMarkName; + } + + @Nullable + @Override public AbstractVcs getVcs() { return HgVcs.getInstance(getProject()); } @@ -163,6 +177,16 @@ public class HgRepositoryImpl extends RepositoryImpl implements HgRepository { } @Override + public boolean hasSubrepos() { + return myInfo.hasSubrepos(); + } + + @NotNull + public Collection<HgNameWithHashInfo> getSubrepos() { + return myInfo.getSubrepos(); + } + + @Override public boolean isFresh() { return myIsFresh; } @@ -199,7 +223,8 @@ public class HgRepositoryImpl extends RepositoryImpl implements HgRepository { return new HgRepoInfo(myReader.readCurrentBranch(), myReader.readCurrentRevision(), myReader.readCurrentTipRevision(), myReader.readState(), myReader.readBranches(), - myReader.readBookmarks(), myReader.readCurrentBookmark(), myReader.readTags(), myReader.readLocalTags()); + myReader.readBookmarks(), myReader.readCurrentBookmark(), myReader.readTags(), myReader.readLocalTags(), + myReader.readSubrepos()); } public void updateConfig() { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryReader.java b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryReader.java index 923087d0b3b2..fab661a99a32 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryReader.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryReader.java @@ -48,10 +48,10 @@ public class HgRepositoryReader { private static Pattern HASH_NAME = Pattern.compile("\\s*([0-9a-fA-F]+)\\s+(.+)"); private static Pattern HASH_STATUS_NAME = Pattern.compile("\\s*([0-9a-fA-F]+)\\s+\\w\\s+(.+)"); - //hash + name_or_revision_num; hash + status_character + name_or_revision_num + //hash + name_or_revision_num; hash + status_character + name_or_revision_num @NotNull private final File myHgDir; // .hg - @NotNull private File myBranchHeadsFile; // .hg/cache/branch* + part depends on version + @NotNull private File myBranchHeadsFile; // .hg/cache/branch* + part depends on version @NotNull private final File myCacheDir; // .hg/cache (does not exist before first commit) @NotNull private final File myCurrentBranch; // .hg/branch @NotNull private final File myBookmarksFile; //.hg/bookmarks @@ -59,6 +59,8 @@ public class HgRepositoryReader { @NotNull private final File myTagsFile; //.hgtags - not in .hg directory!!! @NotNull private final File myLocalTagsFile; // .hg/localtags @NotNull private final File myDirStateFile; // .hg/dirstate + @NotNull private final File mySubrepoFile; // .hgsubstate + @NotNull private final VcsLogObjectsFactory myVcsObjectsFactory; private final boolean myStatusInBranchFile; @NotNull final HgVcs myVcs; @@ -76,6 +78,7 @@ public class HgRepositoryReader { myCurrentBookmark = new File(myHgDir, "bookmarks.current"); myLocalTagsFile = new File(myHgDir, "localtags"); myTagsFile = new File(myHgDir.getParentFile(), ".hgtags"); + mySubrepoFile = new File(myHgDir.getParentFile(), ".hgsubstate"); myDirStateFile = new File(myHgDir, "dirstate"); myVcsObjectsFactory = ServiceManager.getService(vcs.getProject(), VcsLogObjectsFactory.class); } @@ -192,6 +195,10 @@ public class HgRepositoryReader { return new File(myHgDir, "merge").exists(); } + public boolean hasSubrepos() { + return mySubrepoFile.exists(); + } + public boolean isRebaseInProgress() { return new File(myHgDir, "rebasestate").exists(); } @@ -248,4 +255,11 @@ public class HgRepositoryReader { public String readCurrentBookmark() { return myCurrentBookmark.exists() ? RepositoryUtil.tryLoadFile(myCurrentBookmark) : null; } + + @NotNull + public Collection<HgNameWithHashInfo> readSubrepos() { + if (!hasSubrepos()) return Collections.emptySet(); + return readReference(mySubrepoFile); + } + } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java b/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java index 05a62338a9ce..9c89e74f8759 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java @@ -32,7 +32,7 @@ import org.jetbrains.annotations.Nullable; import org.zmlx.hg4idea.HgProjectSettings; import org.zmlx.hg4idea.HgUpdater; import org.zmlx.hg4idea.HgVcs; -import org.zmlx.hg4idea.action.HgBranchPopup; +import org.zmlx.hg4idea.branch.HgBranchPopup; import org.zmlx.hg4idea.repo.HgRepository; import org.zmlx.hg4idea.util.HgUtil; diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.form b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.form index 38dc6eb52908..cc1ea793d2c7 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.form +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.form @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.zmlx.hg4idea.ui.HgConfigurationProjectPanel"> - <grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> + <grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <margin top="0" left="0" bottom="0" right="0"/> <constraints> - <xy x="20" y="20" width="623" height="228"/> + <xy x="20" y="20" width="623" height="299"/> </constraints> <properties/> <border type="none"/> @@ -11,7 +11,7 @@ <grid id="8c1f" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <margin top="0" left="0" bottom="0" right="0"/> <constraints> - <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="2" indent="0" use-parent-layout="false"/> + <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="2" indent="0" use-parent-layout="false"/> </constraints> <properties/> <clientProperties> @@ -39,16 +39,43 @@ </component> </children> </grid> + <vspacer id="4088f"> + <constraints> + <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/> + </constraints> + </vspacer> + <grid id="c2117" binding="myRepositorySettingsPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> + <margin top="0" left="0" bottom="0" right="0"/> + <constraints> + <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="2" indent="0" use-parent-layout="false"/> + </constraints> + <properties/> + <clientProperties> + <BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/> + </clientProperties> + <border type="etched" title="Repository Settings"/> + <children> + <component id="fadf2" class="com.intellij.ui.components.JBCheckBox" binding="mySyncBranchControl"> + <constraints> + <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> + </constraints> + <properties> + <text value="Control &branches from different roots synchronously"/> + <toolTipText value="If selected, you would be able to checkout, compare, delete and create new branches in all Git roots with a single action"/> + </properties> + </component> + </children> + </grid> <grid id="4e3f3" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <margin top="0" left="0" bottom="0" right="0"/> <constraints> - <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/> + <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/> </constraints> <properties/> <clientProperties> <BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/> </clientProperties> - <border type="etched" title="Path to hg executable"/> + <border type="none"/> <children> <component id="83ec6" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myPathSelector" custom-create="true"> <constraints> @@ -65,7 +92,7 @@ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> </constraints> <properties> - <text value="&Specify executable path"/> + <text value="&Path to hg executable"/> </properties> </component> <component id="61549" class="javax.swing.JButton" binding="myTestButton"> @@ -80,11 +107,6 @@ </component> </children> </grid> - <vspacer id="4088f"> - <constraints> - <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/> - </constraints> - </vspacer> </children> </grid> <buttonGroups> diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.java index 2aff9073d266..619536de0f88 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.java @@ -12,14 +12,18 @@ // limitations under the License. package org.zmlx.hg4idea.ui; +import com.intellij.dvcs.branch.DvcsBranchSync; +import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.TextFieldWithBrowseButton; +import com.intellij.ui.components.JBCheckBox; import org.jetbrains.annotations.NotNull; import org.zmlx.hg4idea.HgProjectSettings; import org.zmlx.hg4idea.HgVcs; import org.zmlx.hg4idea.HgVcsMessages; +import org.zmlx.hg4idea.repo.HgRepositoryManager; import org.zmlx.hg4idea.util.HgUtil; import org.zmlx.hg4idea.util.HgVersion; @@ -36,6 +40,8 @@ public class HgConfigurationProjectPanel { private JCheckBox myIgnoredWhitespacesInAnnotationsCbx; private TextFieldWithBrowseButton myPathSelector; private JButton myTestButton; + private JBCheckBox mySyncBranchControl; + private JPanel myRepositorySettingsPanel; private final HgVcs myVcs; public HgConfigurationProjectPanel(@NotNull HgProjectSettings projectSettings, @NotNull Project project) { @@ -58,12 +64,15 @@ public class HgConfigurationProjectPanel { ); } }); + final HgRepositoryManager repositoryManager = ServiceManager.getService(project, HgRepositoryManager.class); + myRepositorySettingsPanel.setVisible(repositoryManager != null && repositoryManager.moreThanOneRoot()); } public boolean isModified() { boolean executableModified = !getCurrentPath().equals(myProjectSettings.getHgExecutable()); return executableModified || myCheckIncomingOutgoingCbx.isSelected() != myProjectSettings.isCheckIncomingOutgoing() || + ((myProjectSettings.getSyncSetting() == DvcsBranchSync.SYNC) != mySyncBranchControl.isSelected()) || myIgnoredWhitespacesInAnnotationsCbx.isSelected() != myProjectSettings.isWhitespacesIgnoredInAnnotations(); } @@ -71,6 +80,7 @@ public class HgConfigurationProjectPanel { myProjectSettings.setCheckIncomingOutgoing(myCheckIncomingOutgoingCbx.isSelected()); myProjectSettings.setIgnoreWhitespacesInAnnotations(myIgnoredWhitespacesInAnnotationsCbx.isSelected()); myProjectSettings.setHgExecutable(getCurrentPath()); + myProjectSettings.setSyncSetting(mySyncBranchControl.isSelected() ? DvcsBranchSync.SYNC : DvcsBranchSync.DONT); myVcs.checkVersion(); } @@ -82,6 +92,7 @@ public class HgConfigurationProjectPanel { myCheckIncomingOutgoingCbx.setSelected(myProjectSettings.isCheckIncomingOutgoing()); myIgnoredWhitespacesInAnnotationsCbx.setSelected(myProjectSettings.isWhitespacesIgnoredInAnnotations()); myPathSelector.setText(myProjectSettings.getGlobalSettings().getHgExecutable()); + mySyncBranchControl.setSelected(myProjectSettings.getSyncSetting() == DvcsBranchSync.SYNC); } public JPanel getPanel() { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java index 3bb14721f0a8..fcf275f70703 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java @@ -41,6 +41,7 @@ import com.intellij.openapi.wm.StatusBar; import com.intellij.openapi.wm.WindowManager; import com.intellij.openapi.wm.impl.status.StatusBarUtil; import com.intellij.ui.GuiUtils; +import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; @@ -584,16 +585,7 @@ public abstract class HgUtil { if (state != HgRepository.State.NORMAL) { branchText += state.toString() + " "; } - return branchText + getActiveBranchName(repository); - } - - @NotNull - public static String getActiveBranchName(@NotNull HgRepository repository) { - String branchOrBookMarkName = repository.getCurrentBookmark(); - if (StringUtil.isEmptyOrSpaces(branchOrBookMarkName)) { - branchOrBookMarkName = repository.getCurrentBranch(); - } - return branchOrBookMarkName; + return branchText + repository.getCurrentBranchName(); } @NotNull @@ -716,4 +708,14 @@ public abstract class HgUtil { } return Couple.of(userName, email); } + + @NotNull + public static List<String> getTargetNames(@NotNull HgRepository repository) { + return ContainerUtil.sorted(ContainerUtil.map(repository.getRepositoryConfig().getPaths(), new Function<String, String>() { + @Override + public String fun(String s) { + return removePasswordIfNeeded(s); + } + })); + } } |