IDEA-115586 Support specifying default base branch and branch prefix for branches created through Task system

This commit is contained in:
Dmitry Avdeev
2013-11-15 15:17:25 +04:00
parent 07fab55341
commit 2ecd8faa20
8 changed files with 154 additions and 42 deletions
@@ -36,15 +36,26 @@ public abstract class VcsTaskHandler {
public TaskInfo(MultiMap<String, String> branches) {
this.branches = branches;
}
public String getName() {
return branches.isEmpty() ? null : branches.keySet().iterator().next();
}
@Override
public boolean equals(Object obj) {
return branches.equals(((TaskInfo)obj).branches);
}
}
private static final ExtensionPointName<VcsTaskHandler> EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.vcs.taskHandler");
public abstract TaskInfo startNewTask(String taskName);
public abstract void switchToTask(TaskInfo taskInfo);
public abstract void switchToTask(TaskInfo taskInfo, Runnable invokeAfter);
public abstract void closeTask(TaskInfo taskInfo, TaskInfo original);
public abstract TaskInfo getActiveTask();
public abstract TaskInfo[] getCurrentTasks();
}
@@ -22,9 +22,11 @@ import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.VcsTaskHandler;
import com.intellij.util.Function;
import com.intellij.util.NullableFunction;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import git4idea.branch.GitBranchUtil;
import git4idea.branch.GitBrancher;
import git4idea.repo.GitRepository;
import git4idea.repo.GitRepositoryManager;
@@ -88,7 +90,7 @@ public class GitTaskHandler extends VcsTaskHandler {
}
@Override
public void switchToTask(TaskInfo taskInfo) {
public void switchToTask(TaskInfo taskInfo, Runnable invokeAfter) {
for (final String branchName : taskInfo.branches.keySet()) {
List<GitRepository> repositories = getRepositories(taskInfo.branches.get(branchName));
List<GitRepository> notFound = ContainerUtil.filter(repositories, new Condition<GitRepository>() {
@@ -102,7 +104,7 @@ public class GitTaskHandler extends VcsTaskHandler {
}
repositories.removeAll(notFound);
if (!repositories.isEmpty()) {
myBrancher.checkout(branchName, repositories, null);
myBrancher.checkout(branchName, repositories, invokeAfter);
}
}
}
@@ -144,6 +146,26 @@ public class GitTaskHandler extends VcsTaskHandler {
return new TaskInfo(branches);
}
@Override
public TaskInfo[] getCurrentTasks() {
List<GitRepository> repositories = myRepositoryManager.getRepositories();
final List<String> names = ContainerUtil.map(repositories, new Function<GitRepository, String>() {
@Override
public String fun(GitRepository repository) {
return repository.getPresentableUrl();
}
});
Collection<String> branches = GitBranchUtil.getCommonBranches(repositories, true);
return ContainerUtil.map2Array(branches, TaskInfo.class, new Function<String, TaskInfo>() {
@Override
public TaskInfo fun(String branchName) {
MultiMap<String, String> map = new MultiMap<String, String>();
map.put(branchName, names);
return new TaskInfo(map);
}
});
}
private List<GitRepository> getRepositories(Collection<String> urls) {
final List<GitRepository> repositories = myRepositoryManager.getRepositories();
return ContainerUtil.mapNotNull(urls, new NullableFunction<String, GitRepository>() {
@@ -542,4 +542,31 @@ public class GitBranchUtil {
return rootCandidate;
}
@NotNull
public static Collection<String> getCommonBranches(Collection<GitRepository> repositories,
boolean local) {
Collection<String> commonBranches = null;
for (GitRepository repository : repositories) {
GitBranchesCollection branchesCollection = repository.getBranches();
Collection<String> names = local
? convertBranchesToNames(branchesCollection.getLocalBranches())
: getBranchNamesWithoutRemoteHead(branchesCollection.getRemoteBranches());
if (commonBranches == null) {
commonBranches = names;
}
else {
commonBranches.retainAll(names);
}
}
if (commonBranches != null) {
ArrayList<String> common = new ArrayList<String>(commonBranches);
Collections.sort(common);
return common;
}
else {
return Collections.emptyList();
}
}
}
@@ -19,7 +19,6 @@ import git4idea.GitBranch;
import git4idea.GitLocalBranch;
import git4idea.GitRemoteBranch;
import git4idea.branch.GitBranchUtil;
import git4idea.branch.GitBranchesCollection;
import git4idea.repo.GitBranchTrackInfo;
import git4idea.repo.GitRepository;
import org.jetbrains.annotations.NotNull;
@@ -78,12 +77,12 @@ public class GitMultiRootBranchConfig {
@NotNull
Collection<String> getLocalBranches() {
return getCommonBranches(true);
return GitBranchUtil.getCommonBranches(myRepositories, true);
}
@NotNull
Collection<String> getRemoteBranches() {
return getCommonBranches(false);
return GitBranchUtil.getCommonBranches(myRepositories, false);
}
/**
@@ -144,33 +143,6 @@ public class GitMultiRootBranchConfig {
return branch == null ? null : branch.findTrackedBranch(repository);
}
@NotNull
private Collection<String> getCommonBranches(boolean local) {
Collection<String> commonBranches = null;
for (GitRepository repository : myRepositories) {
GitBranchesCollection branchesCollection = repository.getBranches();
Collection<String> names = local
? GitBranchUtil.convertBranchesToNames(branchesCollection.getLocalBranches())
: GitBranchUtil.getBranchNamesWithoutRemoteHead(branchesCollection.getRemoteBranches());
if (commonBranches == null) {
commonBranches = names;
}
else {
commonBranches.retainAll(names);
}
}
if (commonBranches != null) {
ArrayList<String> common = new ArrayList<String>(commonBranches);
Collections.sort(common);
return common;
}
else {
return Collections.emptyList();
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
@@ -73,7 +73,7 @@
</component>
</children>
</grid>
<grid id="637f6" binding="myVcsPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="637f6" binding="myVcsPanel" layout-manager="GridLayoutManager" row-count="2" column-count="4" 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="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -96,7 +96,7 @@
</component>
<component id="3b431" class="javax.swing.JTextField" binding="myChangelistName">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<grid row="1" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
@@ -120,6 +120,21 @@
<text value="Create change&amp;list"/>
</properties>
</component>
<component id="e6ce7" class="com.intellij.openapi.ui.ComboBox" binding="myBranchFrom">
<constraints>
<grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="2cb41" class="com.intellij.ui.components.JBLabel" binding="myFromLabel">
<constraints>
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="e6ce7"/>
<text value="&amp;from"/>
</properties>
</component>
</children>
</grid>
</children>
@@ -16,19 +16,26 @@
package com.intellij.tasks.actions;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.options.binding.BindControl;
import com.intellij.openapi.options.binding.ControlBinder;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.ValidationInfo;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vcs.VcsTaskHandler;
import com.intellij.openapi.vcs.VcsType;
import com.intellij.tasks.*;
import com.intellij.tasks.impl.TaskManagerImpl;
import com.intellij.tasks.impl.TaskUtil;
import com.intellij.ui.ColoredListCellRenderer;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.ui.components.JBLabel;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -42,6 +49,7 @@ import java.awt.event.ActionListener;
*/
public class OpenTaskDialog extends DialogWrapper {
private final static Logger LOG = Logger.getInstance("#com.intellij.tasks.actions.SimpleOpenTaskDialog");
public static final String START_FROM_BRANCH = "start.from.branch";
private JPanel myPanel;
@BindControl(value = "clearContext", instant = true)
@@ -53,9 +61,12 @@ public class OpenTaskDialog extends DialogWrapper {
private JTextField myChangelistName;
private JBCheckBox myCreateBranch;
private JBCheckBox myCreateChangelist;
private JBLabel myFromLabel;
private ComboBox myBranchFrom;
private final Project myProject;
private final Task myTask;
private VcsTaskHandler myVcsTaskHandler;
public OpenTaskDialog(@NotNull final Project project, @NotNull final Task task) {
super(project, false);
@@ -100,6 +111,48 @@ public class OpenTaskDialog extends DialogWrapper {
myCreateBranch.setSelected(false);
myCreateBranch.setVisible(false);
myBranchName.setVisible(false);
myFromLabel.setVisible(false);
myBranchFrom.setVisible(false);
}
else {
VcsTaskHandler[] handlers = VcsTaskHandler.getAllHandlers(project);
for (VcsTaskHandler handler : handlers) {
VcsTaskHandler.TaskInfo[] tasks = handler.getCurrentTasks();
if (tasks.length > 0) {
myVcsTaskHandler = handler;
myBranchFrom.setModel(new DefaultComboBoxModel(tasks));
final String startFrom = PropertiesComponent.getInstance(project).getValue(START_FROM_BRANCH);
VcsTaskHandler.TaskInfo info = null;
if (startFrom != null) {
info = ContainerUtil.find(tasks, new Condition<VcsTaskHandler.TaskInfo>() {
@Override
public boolean value(VcsTaskHandler.TaskInfo taskInfo) {
return startFrom.equals(taskInfo.getName());
}
});
}
if (info == null) {
info = handler.getActiveTask();
}
myBranchFrom.setSelectedItem(info);
myBranchFrom.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
VcsTaskHandler.TaskInfo item = (VcsTaskHandler.TaskInfo)myBranchFrom.getSelectedItem();
if (item != null) {
PropertiesComponent.getInstance(project).setValue(START_FROM_BRANCH, item.getName());
}
}
});
break;
}
}
myBranchFrom.setRenderer(new ColoredListCellRenderer<VcsTaskHandler.TaskInfo>() {
@Override
protected void customizeCellRenderer(JList list, VcsTaskHandler.TaskInfo value, int index, boolean selected, boolean hasFocus) {
append(value.getName());
}
});
}
myBranchName.setText(taskManager.suggestBranchName(task));
@@ -122,7 +175,7 @@ public class OpenTaskDialog extends DialogWrapper {
}
public void createTask() {
TaskManagerImpl taskManager = (TaskManagerImpl)TaskManager.getManager(myProject);
final TaskManagerImpl taskManager = (TaskManagerImpl)TaskManager.getManager(myProject);
taskManager.getState().markAsInProgress = isMarkAsInProgress();
taskManager.getState().createChangelist = myCreateChangelist.isSelected();
@@ -138,13 +191,21 @@ public class OpenTaskDialog extends DialogWrapper {
LOG.warn(ex);
}
}
LocalTask activeTask = taskManager.getActiveTask();
LocalTask localTask = taskManager.activateTask(myTask, isClearContext());
final LocalTask activeTask = taskManager.getActiveTask();
final LocalTask localTask = taskManager.activateTask(myTask, isClearContext());
if (myCreateChangelist.isSelected()) {
taskManager.createChangeList(localTask, myChangelistName.getText());
}
if (myCreateBranch.isSelected()) {
taskManager.createBranch(localTask, activeTask, myBranchName.getText());
VcsTaskHandler.TaskInfo item = (VcsTaskHandler.TaskInfo)myBranchFrom.getSelectedItem();
if (item != null && !item.equals(myVcsTaskHandler.getActiveTask())) {
myVcsTaskHandler.switchToTask(item, new Runnable() {
@Override
public void run() {
taskManager.createBranch(localTask, activeTask, myBranchName.getText());
}
});
}
}
if (myTask.getType() == TaskType.EXCEPTION && AnalyzeTaskStacktraceAction.hasTexts(myTask)) {
AnalyzeTaskStacktraceAction.analyzeStacktrace(myTask, myProject);
@@ -379,11 +379,15 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe
List<BranchInfo> branches = task.getBranches(false);
VcsTaskHandler.TaskInfo info = fromBranches(branches);
switchBranch(info);
return task;
}
public void switchBranch(VcsTaskHandler.TaskInfo info) {
VcsTaskHandler[] handlers = VcsTaskHandler.getAllHandlers(myProject);
for (VcsTaskHandler handler : handlers) {
handler.switchToTask(info);
handler.switchToTask(info, null);
}
return task;
}
private static VcsTaskHandler.TaskInfo fromBranches(List<BranchInfo> branches) {
@@ -69,7 +69,7 @@ public class TaskBranchesTest extends PlatformTestCase {
assertEquals(2, repository.getBranches().getLocalBranches().size());
assertEquals(first, repository.getCurrentBranch().getName());
handler.switchToTask(defaultInfo);
handler.switchToTask(defaultInfo, null);
assertEquals("master", repository.getCurrentBranch().getName());
final String second = "second";