mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
VCS: change lists index refactoring (simplifying) + IDEADEV-31378 (NPE: ChangeListManagerImpl.getChange)
This commit is contained in:
@@ -228,14 +228,14 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
myChangesViewManager.scheduleRefresh();
|
||||
}
|
||||
|
||||
final ChangeListManagerGate gate = changeListWorker.createSelfGate();
|
||||
|
||||
// do actual requests about file statuses
|
||||
final UpdatingChangeListBuilder builder = new UpdatingChangeListBuilder(changeListWorker, composite, new Getter<Boolean>() {
|
||||
public Boolean get() {
|
||||
return myUpdater.isStopped();
|
||||
}
|
||||
}, updateUnversionedFiles, myIgnoredIdeaLevel);
|
||||
|
||||
final ChangeListManagerGate gate = changeListWorker.createSelfGate();
|
||||
}, updateUnversionedFiles, myIgnoredIdeaLevel, gate);
|
||||
|
||||
for (final VcsDirtyScope scope : scopes) {
|
||||
final AbstractVcs vcs = scope.getVcs();
|
||||
@@ -253,15 +253,15 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
|
||||
synchronized (myDataLock) {
|
||||
// do same modifications to change lists as was done during update + do delayed notifications
|
||||
if (wasEverythingDirty) {
|
||||
changeListWorker.notifyDoneProcessingChanges(myListeners);
|
||||
}
|
||||
myModifier.exitUpdate();
|
||||
myModifier.apply(changeListWorker);
|
||||
myModifier.clearQueue();
|
||||
// update member from copy
|
||||
myWorker.takeData(changeListWorker);
|
||||
|
||||
if (wasEverythingDirty) {
|
||||
changeListWorker.notifyDoneProcessingChanges(myListeners);
|
||||
}
|
||||
if (updateUnversionedFiles) {
|
||||
boolean statusChanged = !myComposite.equals(composite);
|
||||
myComposite = composite;
|
||||
@@ -524,9 +524,8 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
@Nullable
|
||||
public Change getChange(VirtualFile file) {
|
||||
synchronized (myDataLock) {
|
||||
final String name = myWorker.getListName(file);
|
||||
if (name != null) {
|
||||
final LocalChangeList list = myWorker.getCopyByName(name);
|
||||
final LocalChangeList list = myWorker.getListCopy(file);
|
||||
if (list != null) {
|
||||
for (Change change : list.getChanges()) {
|
||||
final ContentRevision afterRevision = change.getAfterRevision();
|
||||
if (afterRevision != null) {
|
||||
@@ -552,9 +551,8 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
return null;
|
||||
}
|
||||
synchronized (myDataLock) {
|
||||
final String name = myWorker.getListName(virtualFile);
|
||||
if (name != null) {
|
||||
final LocalChangeList list = myWorker.getCopyByName(name);
|
||||
final LocalChangeList list = myWorker.getListCopy(virtualFile);
|
||||
if (list != null) {
|
||||
for (Change change : list.getChanges()) {
|
||||
final ContentRevision afterRevision = change.getAfterRevision();
|
||||
if (afterRevision != null && afterRevision.getFile().equals(file)) {
|
||||
|
||||
@@ -41,7 +41,6 @@ public class ChangeListWorker implements ChangeListsWriteOperations {
|
||||
LocalChangeList defaultList = null;
|
||||
for (LocalChangeList changeList : worker.myMap.values()) {
|
||||
final LocalChangeList copy = changeList.copy();
|
||||
((LocalChangeListImpl) copy).setLocalListener(myIdx);
|
||||
|
||||
final String changeListName = copy.getName();
|
||||
myMap.put(changeListName, copy);
|
||||
@@ -102,24 +101,16 @@ public class ChangeListWorker implements ChangeListsWriteOperations {
|
||||
return list != null;
|
||||
}
|
||||
|
||||
public void startProcessingChanges(@NotNull final String name, final VcsDirtyScope scope) {
|
||||
final LocalChangeList changeList = myMap.get(name);
|
||||
if (changeList != null) {
|
||||
((LocalChangeListImpl) changeList).startProcessingChanges(myProject, scope);
|
||||
}
|
||||
}
|
||||
|
||||
public LocalChangeList addChangeList(@NotNull final String name, @Nullable final String description) {
|
||||
return addChangeList(name, description, false);
|
||||
}
|
||||
|
||||
public LocalChangeList addChangeList(@NotNull final String name, @Nullable final String description, final boolean inUpdate) {
|
||||
LocalChangeList addChangeList(@NotNull final String name, @Nullable final String description, final boolean inUpdate) {
|
||||
final boolean contains = myMap.containsKey(name);
|
||||
LOG.assertTrue(! contains, "Attempt to create duplicate changelist " + name);
|
||||
if (! contains) {
|
||||
final LocalChangeListImpl newList = (LocalChangeListImpl) LocalChangeList.createEmptyChangeList(myProject, name);
|
||||
newList.setLocalListener(myIdx);
|
||||
|
||||
|
||||
if (description != null) {
|
||||
newList.setComment(description);
|
||||
}
|
||||
@@ -137,6 +128,7 @@ public class ChangeListWorker implements ChangeListsWriteOperations {
|
||||
final LocalChangeList changeList = myMap.get(name);
|
||||
if (changeList != null) {
|
||||
((LocalChangeListImpl) changeList).addChange(change);
|
||||
myIdx.changeAdded(change);
|
||||
}
|
||||
return changeList != null;
|
||||
}
|
||||
@@ -145,9 +137,13 @@ public class ChangeListWorker implements ChangeListsWriteOperations {
|
||||
assert myDefault != null;
|
||||
for (LocalChangeList list : myMap.values()) {
|
||||
if (list.isDefault()) continue;
|
||||
if (((LocalChangeListImpl) list).processChange(change)) return;
|
||||
if (((LocalChangeListImpl) list).processChange(change)) {
|
||||
myIdx.changeAdded(change);
|
||||
return;
|
||||
}
|
||||
}
|
||||
((LocalChangeListImpl) myDefault).processChange(change);
|
||||
myIdx.changeAdded(change);
|
||||
}
|
||||
|
||||
public boolean removeChangeList(@NotNull String name) {
|
||||
@@ -161,7 +157,6 @@ public class ChangeListWorker implements ChangeListsWriteOperations {
|
||||
final String listName = list.getName();
|
||||
|
||||
for (Change change : list.getChanges()) {
|
||||
myIdx.changeRemoved(listName, change);
|
||||
((LocalChangeListImpl) myDefault).addChange(change);
|
||||
}
|
||||
|
||||
@@ -195,7 +190,6 @@ public class ChangeListWorker implements ChangeListsWriteOperations {
|
||||
((LocalChangeListImpl) list).setNameImpl(toName);
|
||||
myMap.remove(fromName);
|
||||
myMap.put(toName, list);
|
||||
myIdx.renamed(toName, list.getChanges());
|
||||
}
|
||||
return list != null;
|
||||
}
|
||||
@@ -227,8 +221,12 @@ public class ChangeListWorker implements ChangeListsWriteOperations {
|
||||
}
|
||||
|
||||
public void notifyStartProcessingChanges(final VcsDirtyScope scope) {
|
||||
final Collection<Change> oldChanges = new ArrayList<Change>();
|
||||
for (LocalChangeList list : myMap.values()) {
|
||||
((LocalChangeListImpl) list).startProcessingChanges(myProject, scope);
|
||||
oldChanges.addAll(((LocalChangeListImpl) list).startProcessingChanges(myProject, scope));
|
||||
}
|
||||
for (Change change : oldChanges) {
|
||||
myIdx.changeRemoved(change);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,37 +254,38 @@ public class ChangeListWorker implements ChangeListsWriteOperations {
|
||||
return myDefault == null ? null : myDefault.getName();
|
||||
}
|
||||
|
||||
public interface LocalListListener {
|
||||
void changeAdded(final String listName, final Change change);
|
||||
void changeRemoved(final String listName, final Change change);
|
||||
}
|
||||
|
||||
|
||||
public List<File> getAffectedPaths() {
|
||||
return myIdx.getAffectedPaths();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<VirtualFile> getAffectedFiles() {
|
||||
return myIdx.getAffectedFiles();
|
||||
final List<VirtualFile> result = new ArrayList<VirtualFile>();
|
||||
for (LocalChangeList list : myMap.values()) {
|
||||
for (Change change : list.getChanges()) {
|
||||
final ContentRevision before = change.getBeforeRevision();
|
||||
final ContentRevision after = change.getAfterRevision();
|
||||
if (before != null) {
|
||||
result.add(before.getFile().getVirtualFile());
|
||||
}
|
||||
if (after != null) {
|
||||
result.add(after.getFile().getVirtualFile());
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// should be tested
|
||||
public String getListName(@NotNull final VirtualFile file) {
|
||||
final String listName = myIdx.getListName(file);
|
||||
if (listName == null || ((listName != null) && myMap.containsKey(listName))) {
|
||||
return listName;
|
||||
}
|
||||
LOG.info("Error: index does not coinside with change lists map. list name: " + listName + " for file: " + file.getPath());
|
||||
public LocalChangeList getListCopy(@NotNull final VirtualFile file) {
|
||||
for (LocalChangeList list : myMap.values()) {
|
||||
for (Change change : list.getChanges()) {
|
||||
if (change.getAfterRevision() != null &&
|
||||
Comparing.equal(change.getAfterRevision().getFile().getVirtualFile(), file)) {
|
||||
return listName;
|
||||
return list.copy();
|
||||
}
|
||||
if (change.getBeforeRevision() != null &&
|
||||
Comparing.equal(change.getBeforeRevision().getFile().getVirtualFile(), file)) {
|
||||
return listName;
|
||||
return list.copy();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -377,4 +376,14 @@ public class ChangeListWorker implements ChangeListsWriteOperations {
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
// used by methods related to user modifications
|
||||
interface UserAccess {
|
||||
|
||||
}
|
||||
|
||||
// used only by UpdatingListBuilder to fill lists
|
||||
interface BuilderAccess {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,108 +1,77 @@
|
||||
package com.intellij.openapi.vcs.changes;
|
||||
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.FileStatus;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ChangeListsIndexes implements ChangeListWorker.LocalListListener {
|
||||
private final Map<VirtualFile, String> myFileToListName;
|
||||
private final Map<VirtualFile, FileStatus> myFileToStatus;
|
||||
public class ChangeListsIndexes {
|
||||
private final Map<String, FileStatus> myFileToStatus;
|
||||
|
||||
ChangeListsIndexes() {
|
||||
myFileToListName = new HashMap<VirtualFile, String>();
|
||||
myFileToStatus = new HashMap<VirtualFile, FileStatus>();
|
||||
myFileToStatus = new HashMap<String, FileStatus>();
|
||||
}
|
||||
|
||||
ChangeListsIndexes(final ChangeListsIndexes idx) {
|
||||
myFileToListName = new HashMap<VirtualFile, String>(idx.myFileToListName);
|
||||
myFileToStatus = new HashMap<VirtualFile, FileStatus>(idx.myFileToStatus);
|
||||
myFileToStatus = new HashMap<String, FileStatus>(idx.myFileToStatus);
|
||||
}
|
||||
|
||||
void add(final VirtualFile file, final String listName, final FileStatus status) {
|
||||
myFileToListName.put(file, listName);
|
||||
myFileToStatus.put(file, status);
|
||||
void add(final FilePath file, final FileStatus status) {
|
||||
myFileToStatus.put(file.getIOFile().getAbsolutePath(), status);
|
||||
}
|
||||
|
||||
void remove(final VirtualFile file) {
|
||||
myFileToListName.remove(file);
|
||||
myFileToStatus.remove(file);
|
||||
}
|
||||
|
||||
void move(final VirtualFile file, final String newListName) {
|
||||
myFileToListName.put(file, newListName);
|
||||
}
|
||||
|
||||
public String getListName(final VirtualFile file) {
|
||||
return myFileToListName.get(file);
|
||||
void remove(final FilePath file) {
|
||||
myFileToStatus.remove(file.getIOFile().getAbsolutePath());
|
||||
}
|
||||
|
||||
public FileStatus getStatus(final VirtualFile file) {
|
||||
return myFileToStatus.get(file);
|
||||
return myFileToStatus.get(new File(file.getPath()).getAbsolutePath());
|
||||
}
|
||||
|
||||
void renamed(final String newName, final Collection<Change> changes) {
|
||||
for (Change change : changes) {
|
||||
addChangeToIdx(newName, change);
|
||||
}
|
||||
public void changeAdded(final Change change) {
|
||||
addChangeToIdx(change);
|
||||
}
|
||||
|
||||
public void changeAdded(final String listName, final Change change) {
|
||||
addChangeToIdx(listName, change);
|
||||
}
|
||||
|
||||
public void changeRemoved(final String listName, final Change change) {
|
||||
public void changeRemoved(final Change change) {
|
||||
final ContentRevision afterRevision = change.getAfterRevision();
|
||||
final ContentRevision beforeRevision = change.getBeforeRevision();
|
||||
if ((isInIdx(afterRevision, listName)) || isInIdx(beforeRevision, listName)) {
|
||||
if (afterRevision != null) {
|
||||
remove(afterRevision.getFile().getVirtualFile());
|
||||
}
|
||||
if (beforeRevision != null) {
|
||||
remove(beforeRevision.getFile().getVirtualFile());
|
||||
}
|
||||
|
||||
if (afterRevision != null) {
|
||||
remove(afterRevision.getFile());
|
||||
}
|
||||
if (beforeRevision != null) {
|
||||
remove(beforeRevision.getFile());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInIdx(final ContentRevision revision, final String listName) {
|
||||
if (revision != null) {
|
||||
final VirtualFile vf = revision.getFile().getVirtualFile();
|
||||
final String idxListName = myFileToListName.get(vf);
|
||||
return Comparing.equal(idxListName, listName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addChangeToIdx(final String listName, final Change change) {
|
||||
private void addChangeToIdx(final Change change) {
|
||||
final ContentRevision afterRevision = change.getAfterRevision();
|
||||
if (afterRevision != null) {
|
||||
add(afterRevision.getFile().getVirtualFile(), listName, change.getFileStatus());
|
||||
add(afterRevision.getFile(), change.getFileStatus());
|
||||
}
|
||||
final ContentRevision beforeRevision = change.getBeforeRevision();
|
||||
if (beforeRevision != null) {
|
||||
if (afterRevision != null) {
|
||||
if (! Comparing.equal(beforeRevision.getFile(), afterRevision.getFile())) {
|
||||
add(beforeRevision.getFile().getVirtualFile(), listName, FileStatus.DELETED);
|
||||
add(beforeRevision.getFile(), FileStatus.DELETED);
|
||||
}
|
||||
} else {
|
||||
add(beforeRevision.getFile().getVirtualFile(), listName, change.getFileStatus());
|
||||
add(beforeRevision.getFile(), change.getFileStatus());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<File> getAffectedPaths() {
|
||||
final List<File> result = new ArrayList<File>(myFileToListName.size());
|
||||
for (VirtualFile virtualFile : myFileToListName.keySet()) {
|
||||
result.add(new File(virtualFile.getPath()));
|
||||
final List<File> result = new ArrayList<File>(myFileToStatus.size());
|
||||
for (String path : myFileToStatus.keySet()) {
|
||||
result.add(new File(path));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<VirtualFile> getAffectedFiles() {
|
||||
return new ArrayList<VirtualFile>(myFileToListName.keySet());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ public class LocalChangeListImpl extends LocalChangeList {
|
||||
private Collection<Change> myOutdatedChanges;
|
||||
private boolean myIsInUpdate = false;
|
||||
private ChangeHashSet myChangesBeforeUpdate;
|
||||
private ChangeListWorker.LocalListListener myLocalListener;
|
||||
|
||||
public static LocalChangeListImpl createEmptyChangeListImpl(Project project, String name) {
|
||||
return new LocalChangeListImpl(project, name);
|
||||
@@ -120,9 +119,6 @@ public class LocalChangeListImpl extends LocalChangeList {
|
||||
synchronized void addChange(Change change) {
|
||||
if (!myIsInUpdate) myReadChangesCache = null;
|
||||
myChanges.add(change);
|
||||
if (myLocalListener != null) {
|
||||
myLocalListener.changeAdded(myName, change);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized Change removeChange(Change change) {
|
||||
@@ -132,17 +128,15 @@ public class LocalChangeListImpl extends LocalChangeList {
|
||||
if (! myIsInUpdate) {
|
||||
myReadChangesCache = null;
|
||||
}
|
||||
if (myLocalListener != null) {
|
||||
myLocalListener.changeRemoved(myName, localChange);
|
||||
}
|
||||
return localChange;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
synchronized void startProcessingChanges(final Project project, @Nullable final VcsDirtyScope scope) {
|
||||
synchronized Collection<Change> startProcessingChanges(final Project project, @Nullable final VcsDirtyScope scope) {
|
||||
createReadChangesCache();
|
||||
final Collection<Change> result = new ArrayList<Change>();
|
||||
myChangesBeforeUpdate = new ChangeHashSet(myChanges);
|
||||
myOutdatedChanges = new ArrayList<Change>();
|
||||
final ExcludedFileIndex fileIndex = ExcludedFileIndex.getInstance(project);
|
||||
@@ -151,9 +145,7 @@ public class LocalChangeListImpl extends LocalChangeList {
|
||||
final ContentRevision after = oldBoy.getAfterRevision();
|
||||
if (scope == null || before != null && scope.belongsTo(before.getFile()) || after != null && scope.belongsTo(after.getFile())
|
||||
|| isIgnoredChange(oldBoy, fileIndex)) {
|
||||
if (myLocalListener != null) {
|
||||
myLocalListener.changeRemoved(myName, oldBoy);
|
||||
}
|
||||
result.add(oldBoy);
|
||||
myIsInUpdate = true;
|
||||
removeChange(oldBoy);
|
||||
myOutdatedChanges.add(oldBoy);
|
||||
@@ -162,6 +154,7 @@ public class LocalChangeListImpl extends LocalChangeList {
|
||||
if (isDefault()) {
|
||||
myIsInUpdate = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean isIgnoredChange(final Change change, final ExcludedFileIndex fileIndex) {
|
||||
@@ -294,8 +287,4 @@ public class LocalChangeListImpl extends LocalChangeList {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void setLocalListener(final ChangeListWorker.LocalListListener localListener) {
|
||||
myLocalListener = localListener;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ public class Modifier implements ChangeListsWriteOperations {
|
||||
}
|
||||
|
||||
public LocalChangeList addChangeList(@NotNull final String name, final String comment) {
|
||||
final AddList command = new AddList(name, comment, myInsideUpdate);
|
||||
final AddList command = new AddList(name, comment);
|
||||
impl(command);
|
||||
return command.getNewListCopy();
|
||||
}
|
||||
|
||||
@@ -19,17 +19,19 @@ class UpdatingChangeListBuilder implements ChangelistBuilder {
|
||||
private final boolean myUpdateUnversioned;
|
||||
private final IgnoredFilesComponent myIgnoredFilesComponent;
|
||||
private final ExcludedFileIndex myIndex;
|
||||
private final ChangeListManagerGate myGate;
|
||||
|
||||
UpdatingChangeListBuilder(final ChangeListWorker changeListWorker,
|
||||
final FileHolderComposite composite,
|
||||
final Getter<Boolean> disposedGetter,
|
||||
final boolean updateUnversioned,
|
||||
final IgnoredFilesComponent ignoredFilesComponent) {
|
||||
final IgnoredFilesComponent ignoredFilesComponent, final ChangeListManagerGate gate) {
|
||||
myChangeListWorker = changeListWorker;
|
||||
myComposite = composite;
|
||||
myDisposedGetter = disposedGetter;
|
||||
myUpdateUnversioned = updateUnversioned;
|
||||
myIgnoredFilesComponent = ignoredFilesComponent;
|
||||
myGate = gate;
|
||||
myIndex = ExcludedFileIndex.getInstance(changeListWorker.getProject());
|
||||
}
|
||||
|
||||
@@ -72,8 +74,7 @@ class UpdatingChangeListBuilder implements ChangelistBuilder {
|
||||
if (changeListName != null) {
|
||||
list = myChangeListWorker.getCopyByName(changeListName);
|
||||
if (list == null) {
|
||||
list = myChangeListWorker.addChangeList(changeListName, null, true);
|
||||
myChangeListWorker.startProcessingChanges(list.getName(), myScope);
|
||||
list = myGate.addChangeList(changeListName, null);
|
||||
}
|
||||
}
|
||||
processChangeInList(change, list);
|
||||
|
||||
@@ -8,17 +8,15 @@ import com.intellij.util.EventDispatcher;
|
||||
public class AddList implements ChangeListCommand {
|
||||
private final String myName;
|
||||
private final String myComment;
|
||||
private final boolean myInsideUpdate;
|
||||
private LocalChangeList myNewListCopy;
|
||||
|
||||
public AddList(final String name, final String comment, final boolean insideUpdate) {
|
||||
public AddList(final String name, final String comment) {
|
||||
myName = name;
|
||||
myComment = comment;
|
||||
myInsideUpdate = insideUpdate;
|
||||
}
|
||||
|
||||
public void apply(final ChangeListWorker worker) {
|
||||
myNewListCopy = worker.addChangeList(myName, myComment, myInsideUpdate);
|
||||
myNewListCopy = worker.addChangeList(myName, myComment);
|
||||
}
|
||||
|
||||
public void doNotify(final EventDispatcher<ChangeListListener> dispatcher) {
|
||||
|
||||
Reference in New Issue
Block a user