IDEA-70996 Tasks and IDE Contexts - Shelving changes

This commit is contained in:
Dmitry Avdeev
2017-10-04 15:13:49 +03:00
parent ea5cb4e8c0
commit b825a05f35
8 changed files with 130 additions and 33 deletions
@@ -20,6 +20,7 @@ import com.intellij.tasks.timeTracking.model.WorkItem;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xmlb.annotations.Attribute;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Date;
import java.util.List;
@@ -54,6 +55,11 @@ public abstract class LocalTask extends Task {
public abstract void removeChangelist(final ChangeListInfo info);
@Nullable
public abstract String getShelfName();
public abstract void setShelfName(String shelfName);
/**
* For serialization only.
* @return two branches per repository: feature-branch itself and original branch to merge into
@@ -62,12 +62,12 @@ public class LocalTaskImpl extends LocalTask {
private boolean myActive;
private List<ChangeListInfo> myChangeLists = new ArrayList<>();
private String myShelfName;
private boolean myRunning = false;
private List<WorkItem> myWorkItems = new ArrayList<>();
private Date myLastPost;
private List<BranchInfo> myBranches = new ArrayList<>();
/** for serialization */
public LocalTaskImpl() {
}
@@ -235,6 +235,7 @@ public class LocalTaskImpl extends LocalTask {
myChangeLists.remove(info);
}
@NotNull
@Override
@Property(surroundWithTag = false)
@@ -257,6 +258,16 @@ public class LocalTaskImpl extends LocalTask {
myBranches.add(info);
}
@Override
public String getShelfName() {
return myShelfName;
}
@Override
public void setShelfName(String shelfName) {
myShelfName = shelfName;
}
public boolean isClosed() {
return myClosed;
}
@@ -33,6 +33,8 @@ import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsTaskHandler;
import com.intellij.openapi.vcs.VcsType;
import com.intellij.openapi.vcs.changes.*;
import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager;
import com.intellij.openapi.vcs.changes.shelf.ShelvedChangeList;
import com.intellij.tasks.*;
import com.intellij.tasks.context.WorkingContextManager;
import com.intellij.ui.ColoredTreeCellRenderer;
@@ -347,6 +349,7 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe
myChangeListManager.setDefaultChangeList(changeList);
}
unshelveChanges(task);
List<BranchInfo> branches = task.getBranches(false);
// we should have exactly one branch per repo
MultiMap<String, BranchInfo> multiMap = new MultiMap<>();
@@ -376,6 +379,31 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe
return task;
}
public void shelveChanges(LocalTask task, @NotNull String shelfName) {
Collection<Change> changes = ChangeListManager.getInstance(myProject).getDefaultChangeList().getChanges();
if (changes.isEmpty()) return;
try {
ShelveChangesManager.getInstance(myProject).shelveChanges(changes, shelfName, true);
task.setShelfName(shelfName);
}
catch (Exception e) {
LOG.warn("Can't shelve changes", e);
}
}
private void unshelveChanges(LocalTask task) {
String name = task.getShelfName();
if (name != null) {
ShelveChangesManager manager = ShelveChangesManager.getInstance(myProject);
for (ShelvedChangeList list : manager.getShelvedChangeLists()) {
if (name.equals(list.DESCRIPTION)) {
manager.unshelveChangeList(list, list.getChanges(myProject), list.getBinaryFiles(), myChangeListManager.getDefaultChangeList(), true);
return;
}
}
}
}
private List<BranchInfo> getAllBranches(final String repo) {
ArrayList<BranchInfo> infos = new ArrayList<>();
VcsTaskHandler[] handlers = VcsTaskHandler.getAllHandlers(myProject);
@@ -442,6 +470,10 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe
private void saveActiveTask() {
myContextManager.saveContext(myActiveTask);
myActiveTask.setUpdated(new Date());
String shelfName = myActiveTask.getShelfName();
if (shelfName != null) {
shelveChanges(myActiveTask, shelfName);
}
}
private LocalTask doActivate(Task origin, boolean explicitly) {
@@ -952,6 +984,7 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe
public boolean createChangelist = true;
public boolean createBranch = true;
public boolean useBranch = false;
public boolean shelveChanges = false;
// close task options
public boolean commitChanges = true;
@@ -17,5 +17,6 @@
<orderEntry type="module" module-name="xdebugger-impl" />
<orderEntry type="module" module-name="xdebugger-api" />
<orderEntry type="library" name="http-client-3.1" level="project" />
<orderEntry type="module" module-name="vcs-impl" />
</component>
</module>
@@ -105,7 +105,7 @@ public class OpenTaskDialog extends DialogWrapper {
}
myAdditionalPanel.setLayout(new BoxLayout(myAdditionalPanel, BoxLayout.Y_AXIS));
myPanels = TaskDialogPanelProvider.getOpenTaskPanels(project, task);
myPanels = TaskDialogPanelProvider.getOpenTaskPanels(project, myTask);
for (TaskDialogPanel panel : myPanels) {
myAdditionalPanel.add(panel.getPanel());
}
@@ -3,12 +3,12 @@
<grid id="27dc6" 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>
<xy x="20" y="20" width="378" height="118"/>
<xy x="20" y="20" width="424" height="143"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<grid id="4e586" binding="myPanel" layout-manager="GridLayoutManager" row-count="3" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="4e586" binding="myPanel" layout-manager="GridLayoutManager" row-count="4" 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="0" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -21,17 +21,7 @@
<children>
<component id="2f42c" class="javax.swing.JTextField" binding="myBranchName">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties>
<enabled value="false"/>
</properties>
</component>
<component id="98846" class="javax.swing.JTextField" binding="myChangelistName">
<constraints>
<grid row="2" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
@@ -41,23 +31,15 @@
</component>
<component id="30060" class="com.intellij.ui.components.JBCheckBox" binding="myCreateBranch" default-binding="true">
<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"/>
<grid row="2" 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="Create &amp;branch"/>
</properties>
</component>
<component id="601c" class="com.intellij.ui.components.JBCheckBox" binding="myCreateChangelist" default-binding="true">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Create change&amp;list"/>
</properties>
</component>
<component id="60274" 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"/>
<grid row="2" 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>
<model/>
@@ -65,7 +47,7 @@
</component>
<component id="a958a" 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"/>
<grid row="2" 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="60274"/>
@@ -74,7 +56,7 @@
</component>
<component id="2ca8c" class="com.intellij.ui.components.JBCheckBox" binding="myUseBranch">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="3" 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="U&amp;se branch"/>
@@ -82,10 +64,36 @@
</component>
<component id="e89ff" class="com.intellij.openapi.ui.ComboBox" binding="myUseBranchCombo">
<constraints>
<grid row="1" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="2" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
<grid row="3" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="2" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="601c" class="com.intellij.ui.components.JBCheckBox" binding="myCreateChangelist" default-binding="true">
<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="Create change&amp;list"/>
</properties>
</component>
<component id="98846" class="javax.swing.JTextField" binding="myChangelistName">
<constraints>
<grid row="0" 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>
<properties>
<enabled value="false"/>
</properties>
</component>
<component id="159" class="com.intellij.ui.components.JBCheckBox" binding="myShelveChanges">
<constraints>
<grid row="1" column="0" row-span="1" col-span="4" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;Shelve current changes"/>
</properties>
</component>
</children>
</grid>
</children>
@@ -52,6 +52,7 @@ public class VcsOpenTaskPanel extends TaskDialogPanel {
private JBLabel myFromLabel;
private JBCheckBox myUseBranch;
private ComboBox<VcsTaskHandler.TaskInfo> myUseBranchCombo;
private JBCheckBox myShelveChanges;
private VcsTaskHandler myVcsTaskHandler;
private static final String START_FROM_BRANCH = "start.from.branch";
@@ -84,6 +85,7 @@ public class VcsOpenTaskPanel extends TaskDialogPanel {
}
});
myCreateChangelist.setSelected(myTaskManager.getState().createChangelist);
myShelveChanges.setSelected(myTaskManager.getState().shelveChanges);
VcsTaskHandler[] handlers = VcsTaskHandler.getAllHandlers(project);
if (handlers.length == 0) {
@@ -167,10 +169,14 @@ public class VcsOpenTaskPanel extends TaskDialogPanel {
@Override
public void commit() {
myTaskManager.getState().createChangelist = myCreateChangelist.isSelected();
myTaskManager.getState().shelveChanges = myShelveChanges.isSelected();
myTaskManager.getState().createBranch = myCreateBranch.isSelected();
myTaskManager.getState().useBranch = myUseBranch.isSelected();
LocalTask localTask = myTaskManager.getActiveTask();
if (myShelveChanges.isSelected()) {
myTaskManager.shelveChanges(myPreviousTask, myPreviousTask.getSummary());
}
if (myCreateChangelist.isSelected()) {
myTaskManager.createChangeList(localTask, myChangelistName.getText());
}
@@ -17,24 +17,30 @@ package com.intellij.tasks.vcs;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.changes.*;
import com.intellij.openapi.vcs.changes.committed.MockAbstractVcs;
import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager;
import com.intellij.openapi.vcs.changes.shelf.ShelvedChangeList;
import com.intellij.openapi.vcs.changes.ui.CommitChangeListDialog;
import com.intellij.openapi.vcs.impl.projectlevelman.AllVcses;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.tasks.*;
import com.intellij.tasks.actions.OpenTaskDialog;
import com.intellij.tasks.impl.LocalTaskImpl;
import com.intellij.tasks.impl.TaskChangelistSupport;
import com.intellij.tasks.impl.TaskManagerImpl;
import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
import com.intellij.vcsUtil.VcsUtil;
import icons.TasksIcons;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@@ -208,7 +214,7 @@ public class TaskVcsTest extends CodeInsightFixtureTestCase {
LocalTask anotherTask = myTaskManager.findTask("TEST-001");
assertNotNull(anotherTask);
addChangeList("Default (1)", "");
addChangeList("Default (1)");
assertEquals(1, anotherTask.getChangeLists().size());
assertEquals(2, defaultTask.getChangeLists().size());
@@ -236,7 +242,7 @@ public class TaskVcsTest extends CodeInsightFixtureTestCase {
public void testTrackContext() {
myTaskManager.getState().trackContextForNewChangelist = true;
addChangeList("New Changelist", "");
addChangeList("New Changelist");
assertEquals(2, myTaskManager.getLocalTasks().size());
assertEquals(2, myChangeListManager.getChangeListsCopy().size());
LocalChangeList newChangeList = myChangeListManager.findChangeList("New Changelist");
@@ -298,7 +304,7 @@ public class TaskVcsTest extends CodeInsightFixtureTestCase {
assertEquals(1, myTaskManager.getLocalTasks().size());
assertEquals(1, myChangeListManager.getChangeListsCopy().size());
LocalChangeList changeList = addChangeList("New Changelist", "");
LocalChangeList changeList = addChangeList("New Changelist");
assertEquals(1, myTaskManager.getLocalTasks().size());
assertEquals(2, myChangeListManager.getChangeListsCopy().size());
@@ -312,8 +318,8 @@ public class TaskVcsTest extends CodeInsightFixtureTestCase {
assertTrue(ContainerUtil.exists(myTaskManager.getLocalTasks(), task -> task.getSummary().equals("New Changelist")));
}
private LocalChangeList addChangeList(String title, String comment) {
final LocalChangeList list = myChangeListManager.addChangeList(title, comment);
private LocalChangeList addChangeList(String title) {
final LocalChangeList list = myChangeListManager.addChangeList(title, "");
new TaskChangelistSupport(getProject(), myTaskManager).addControls(new JPanel(), null).consume(list);
return list;
}
@@ -412,6 +418,32 @@ public class TaskVcsTest extends CodeInsightFixtureTestCase {
assertEquals("1-contains-Illegal$Symbols", myTaskManager.suggestBranchName(withIllegalSymbolsInIssue));
}
public void testShelveChanges() {
LocalTask activeTask = myTaskManager.getActiveTask();
addChanges(myChangeListManager.getDefaultChangeList());
myTaskManager.getState().shelveChanges = true;
LocalTaskImpl task = new LocalTaskImpl("id", "summary");
OpenTaskDialog dialog = new OpenTaskDialog(getProject(), task);
try {
dialog.createTask();
assertEquals(activeTask.getSummary(), activeTask.getShelfName());
List<ShelvedChangeList> lists = ShelveChangesManager.getInstance(getProject()).getShelvedChangeLists();
assertTrue(lists.stream().anyMatch(list -> list.DESCRIPTION.equals(activeTask.getShelfName())));
assertEmpty(myChangeListManager.getDefaultChangeList().getChanges());
myTaskManager.activateTask(activeTask, true);
Collection<Change> changes = myChangeListManager.getDefaultChangeList().getChanges();
assertNotEmpty(changes);
}
finally {
dialog.close(DialogWrapper.OK_EXIT_CODE);
}
UIUtil.dispatchAllInvocationEvents();
}
@Override
public void setUp() throws Exception {
super.setUp();