diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java index 074c5a4fbcce..d3cf2b832d0d 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java @@ -70,10 +70,10 @@ public abstract class ChangeListManager implements ChangeListModification { @NotNull public abstract Collection getAllChanges(); - @Nullable + @NotNull public abstract LocalChangeList getDefaultChangeList(); - @Nullable + @NotNull public abstract String getDefaultListName(); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java index 52a93d6d608b..acfa695a6700 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java @@ -282,9 +282,6 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec @CalledInAwt private void initializeForNewProject() { synchronized (myDataLock) { - if (myWorker.isEmpty()) { - setDefaultChangeList(myWorker.addChangeList(LocalChangeList.DEFAULT_NAME, null, null)); - } if (!Registry.is("ide.hide.excluded.files") && !myExcludedConvertedToIgnored) { convertExcludedToIgnored(); myExcludedConvertedToIgnored = true; @@ -918,8 +915,8 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec myChangesViewManager.scheduleRefresh(); } + @NotNull @Override - @Nullable public LocalChangeList getDefaultChangeList() { synchronized (myDataLock) { return myWorker.getDefaultListCopy(); @@ -1246,9 +1243,6 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec synchronized (myDataLock) { ChangeListManagerSerialization.readExternal(element, myIgnoredIdeaLevel, myWorker); - if (!myWorker.isEmpty() && myWorker.getDefaultListCopy() == null) { - myWorker.setDefault(myWorker.getListsCopy().get(0).getName()); - } } myExcludedConvertedToIgnored = Boolean.parseBoolean(JDOMExternalizerUtil.readField(element, EXCLUDED_CONVERTED_TO_IGNORED_OPTION)); myConflictTracker.loadState(element); @@ -1397,6 +1391,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec } } + @NotNull @Override public String getDefaultListName() { synchronized (myDataLock) { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerSerialization.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerSerialization.java index 5090e4279810..3bbf4a9e35a3 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerSerialization.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerSerialization.java @@ -23,10 +23,7 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.io.File; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; class ChangeListManagerSerialization { @NonNls private static final String ATT_ID = "id"; @@ -66,9 +63,11 @@ class ChangeListManagerSerialization { } public static void readExternal(@NotNull Element element, @NotNull IgnoredFilesComponent ignoredIdeaLevel, @NotNull ChangeListWorker worker) { + List lists = new ArrayList<>(); for (Element listNode : element.getChildren(NODE_LIST)) { - readChangeList(listNode, worker); + lists.add(readChangeList(listNode, worker.getProject())); } + worker.setChangeLists(removeDuplicatedLists(lists)); ignoredIdeaLevel.clear(); for (Element ignoredNode : element.getChildren(NODE_IGNORED)) { @@ -85,6 +84,35 @@ class ChangeListManagerSerialization { ignoredIdeaLevel.setDirectoriesManuallyRemovedFromIgnored(manuallyRemovedFromIgnoredPaths); } + @NotNull + private static Collection removeDuplicatedLists(@NotNull List lists) { + // workaround for loading incorrect settings (with duplicate changelist names) + + boolean hasDefault = false; + Map map = new HashMap<>(); + for (LocalChangeListImpl list : lists) { + if (list.isDefault()) { + if (hasDefault) { + list.setDefault(false); + } + hasDefault = true; + } + + LocalChangeListImpl otherList = map.get(list.getName()); + if (otherList == null) { + map.put(list.getName(), list); + } + else { + for (Change change : list.getChanges()) { + otherList.addChange(change); + } + + if (list.isDefault()) otherList.setDefault(true); + } + } + return map.values(); + } + @NotNull private static Element writeChangeList(@NotNull LocalChangeList list) { Element listNode = new Element(NODE_LIST); @@ -107,27 +135,27 @@ class ChangeListManagerSerialization { return listNode; } - private static void readChangeList(@NotNull Element listNode, @NotNull ChangeListWorker worker) { + @NotNull + private static LocalChangeListImpl readChangeList(@NotNull Element listNode, @NotNull Project project) { String id = listNode.getAttributeValue(ATT_ID); String name = listNode.getAttributeValue(ATT_NAME); String comment = listNode.getAttributeValue(ATT_COMMENT); - // workaround for loading incorrect settings (with duplicate changelist names) - LocalChangeList list = worker.getCopyByName(name); - if (list == null) { - list = worker.addChangeList(id, name, comment, false, null); - } + LocalChangeListImpl list = LocalChangeListImpl.createEmptyChangeListImpl(project, name, id); + list.setComment(comment); for (Element changeNode : listNode.getChildren(NODE_CHANGE)) { - worker.addChangeToList(name, readChange(changeNode), null); + list.addChange(readChange(changeNode)); } if (ATT_VALUE_TRUE.equals(listNode.getAttributeValue(ATT_DEFAULT))) { - worker.setDefault(list.getName()); + list.setDefault(true); } if (ATT_VALUE_TRUE.equals(listNode.getAttributeValue(ATT_READONLY))) { list.setReadOnly(true); } + + return list; } @NotNull diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java index b3b442676b21..8c17f1da29de 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java @@ -61,6 +61,8 @@ public class ChangeListWorker implements ChangeListsWriteOperations { myDelta = new ChangesDelta(deltaListener); myListsToDisappear = ContainerUtil.newLinkedHashSet(); + + ensureDefaultListExists(); } private ChangeListWorker(ChangeListWorker worker) { @@ -70,30 +72,30 @@ public class ChangeListWorker implements ChangeListsWriteOperations { myDelta = worker.myDelta; myListsToDisappear = ContainerUtil.newLinkedHashSet(worker.myListsToDisappear); - LocalChangeListImpl defaultList = null; - for (LocalChangeListImpl changeList : worker.myMap.values()) { - final LocalChangeListImpl copy = changeList.copy(); - final String changeListName = copy.getName(); - myMap.put(changeListName, copy); + for (LocalChangeListImpl list : worker.myMap.values()) { + LocalChangeListImpl copy = list.copy(); + myMap.put(copy.getName(), copy); if (copy.isDefault()) { - defaultList = copy; + if (myDefault != null) LOG.error("multiple default lists found when copy"); + myDefault = copy; } } - if (defaultList == null) { - LOG.info("default list not found when copy"); - defaultList = myMap.get(worker.getDefaultListName()); - } - if (defaultList == null) { - LOG.info("default list not found when copy in original object too"); - if (!myMap.isEmpty()) { - defaultList = myMap.values().iterator().next(); - } else { - // can be when there's no vcs configured - ///LOG.error("no changelists at all"); - } + ensureDefaultListExists(); + } + + private void ensureDefaultListExists() { + if (myDefault != null) return; + + if (!myMap.isEmpty()) { + myDefault = myMap.values().iterator().next(); + myDefault.setDefault(true); + } + else { + myDefault = LocalChangeListImpl.createEmptyChangeListImpl(myProject, LocalChangeList.DEFAULT_NAME, null); + myDefault.setDefault(true); + myMap.put(myDefault.getName(), myDefault); } - myDefault = defaultList; } public void onAfterWorkerSwitch(@NotNull final ChangeListWorker previous) { @@ -163,20 +165,18 @@ public class ChangeListWorker implements ChangeListsWriteOperations { } /** - * @return if list with name exists, return previous default list name or null of there wasn't previous + * @return previous default list name or null if nothing was done */ @Nullable public String setDefault(String name) { - final LocalChangeListImpl newDefault = myMap.get(name); + LocalChangeListImpl newDefault = myMap.get(name); if (newDefault == null) { return null; } - String previousName = null; - if (myDefault != null) { - myDefault.setDefault(false); - previousName = myDefault.getName(); - } + String previousName = myDefault.getName(); + + myDefault.setDefault(false); newDefault.setDefault(true); myDefault = newDefault; @@ -193,24 +193,21 @@ public class ChangeListWorker implements ChangeListsWriteOperations { @NotNull public LocalChangeList addChangeList(@NotNull String name, @Nullable String comment, @Nullable Object data) { - return addChangeList(null, name, comment, false, data); + return addChangeList(name, comment, false, data); } @NotNull - LocalChangeList addChangeList(@Nullable String id, @NotNull String name, @Nullable String description, boolean inUpdate, - @Nullable Object data) { + private LocalChangeList addChangeList(@NotNull String name, @Nullable String description, boolean inUpdate, + @Nullable Object data) { if (myMap.containsKey(name)) { LOG.error("Attempt to create duplicate changelist " + name); return myMap.get(name).copy(); } - LocalChangeListImpl newList = LocalChangeListImpl.createEmptyChangeListImpl(myProject, name, id); + LocalChangeListImpl newList = LocalChangeListImpl.createEmptyChangeListImpl(myProject, name, null); + newList.setComment(description); newList.setData(data); - if (description != null) { - newList.setComment(description); - } - myMap.put(name, newList); if (inUpdate) { startProcessingChanges(newList); // this is executed only when use through GATE @@ -218,6 +215,26 @@ public class ChangeListWorker implements ChangeListsWriteOperations { return newList.copy(); } + void setChangeLists(@NotNull Collection lists) { + myDefault = null; + myMap.clear(); + myIdx.clear(); + + for (LocalChangeListImpl list : lists) { + myMap.put(list.getName(), list); + if (list.isDefault()) { + if (myDefault != null) LOG.error("multiple default lists found when copy"); + myDefault = list; + } + + for (Change change : list.getChanges()) { + myIdx.changeAdded(change, null); + } + } + + ensureDefaultListExists(); + } + private void addChangeToList(@NotNull LocalChangeListImpl list, @NotNull Change change, VcsKey vcsKey) { list.addChange(change); myIdx.changeAdded(change, vcsKey); @@ -235,7 +252,6 @@ public class ChangeListWorker implements ChangeListsWriteOperations { public void addChangeToCorrespondingList(@NotNull Change change, VcsKey vcsKey) { final String path = ChangesUtil.getFilePath(change).getPath(); LOG.debug("[addChangeToCorrespondingList] for change " + path + " type: " + change.getType() + " have before revision: " + (change.getBeforeRevision() != null)); - assert myDefault != null; for (LocalChangeListImpl list : myMap.values()) { OpenTHashSet changesBeforeUpdate = myChangesBeforeUpdateMap.get(list); if (changesBeforeUpdate.contains(change)) { @@ -318,9 +334,9 @@ public class ChangeListWorker implements ChangeListsWriteOperations { return myMap.isEmpty(); } - @Nullable + @NotNull public LocalChangeList getDefaultListCopy() { - return myDefault == null ? null : myDefault.copy(); + return myDefault.copy(); } @NotNull @@ -482,8 +498,9 @@ public class ChangeListWorker implements ChangeListsWriteOperations { return result; } + @NotNull public String getDefaultListName() { - return myDefault == null ? null : myDefault.getName(); + return myDefault.getName(); } @NotNull @@ -704,7 +721,7 @@ public class ChangeListWorker implements ChangeListsWriteOperations { @NotNull @Override public LocalChangeList addChangeList(@NotNull String name, @Nullable String comment) { - return myWorker.addChangeList(null, name, comment, true, null); + return myWorker.addChangeList(name, comment, true, null); } @NotNull diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListsIndexes.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListsIndexes.java index 87a9b051630a..6833ddd2b0f5 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListsIndexes.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListsIndexes.java @@ -170,6 +170,10 @@ public class ChangeListsIndexes { return result; } + public void clear() { + myMap.clear(); + } + @NotNull public NavigableSet getAffectedPaths() { return Sets.unmodifiableNavigableSet(myMap.navigableKeySet()); diff --git a/platform/vcs-impl/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java b/platform/vcs-impl/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java index 3f417c6f396c..6f89d4acb78e 100644 --- a/platform/vcs-impl/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java +++ b/platform/vcs-impl/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java @@ -142,6 +142,7 @@ public class MockChangeListManager extends ChangeListManagerEx { throw new UnsupportedOperationException(); } + @NotNull @Override public LocalChangeList getDefaultChangeList() { return myActiveChangeList; @@ -294,6 +295,7 @@ public class MockChangeListManager extends ChangeListManagerEx { throw new UnsupportedOperationException(); } + @NotNull @Override public String getDefaultListName() { throw new UnsupportedOperationException();