mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-65111 MembershipMap.putOptimal not optimal
This commit is contained in:
@@ -543,5 +543,9 @@ public abstract class AbstractVcs<ComList extends CommittedChangeList> extends S
|
||||
if (myRollbackEnvironment != null) throw new IllegalStateException("Attempt to redefine rollback environment");
|
||||
myRollbackEnvironment = rollbackEnvironment;
|
||||
}
|
||||
|
||||
public boolean reportsIgnoredDirectories() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.openapi.vcs;
|
||||
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.PairProcessor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -55,6 +56,37 @@ public class AreaMap<Key, Val> {
|
||||
putImpl(key, val);
|
||||
}
|
||||
|
||||
protected int putIfNoParent(final Key key, final Val val) {
|
||||
if(myMap.put(key, val) != null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (myKeys.isEmpty()) {
|
||||
myKeys.add(key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
final int idx = Collections.binarySearch(myKeys, key, myComparator);
|
||||
if (idx < 0) {
|
||||
// insertion, no copy exist
|
||||
final int insertionIdx = - idx - 1;
|
||||
// check parent
|
||||
for (final ListIterator<Key> listIterator = myKeys.listIterator(insertionIdx); listIterator.hasPrevious();) {
|
||||
final Key previous = listIterator.previous();
|
||||
if (myKeysResemblance.process(previous, key)) {
|
||||
myMap.remove(key);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
// insertionIdx not necessarily exist
|
||||
myKeys.add(insertionIdx, key);
|
||||
return insertionIdx;
|
||||
}
|
||||
assert true;
|
||||
myMap.remove(key);
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected int putImpl(final Key key, final Val val) {
|
||||
myMap.put(key, val);
|
||||
|
||||
@@ -115,8 +147,8 @@ public class AreaMap<Key, Val> {
|
||||
// take item before
|
||||
final int itemBeforeIdx = insertionIdx - 1;
|
||||
if (itemBeforeIdx >= 0) {
|
||||
for (int i = itemBeforeIdx; i >= 0; -- i) {
|
||||
final Key candidate = myKeys.get(i);
|
||||
for (ListIterator<Key> iterator = myKeys.listIterator(itemBeforeIdx + 1); iterator.hasPrevious(); ) {
|
||||
final Key candidate = iterator.previous();
|
||||
if (! myKeysResemblance.process(candidate, key)) continue;
|
||||
if (consumer.process(candidate, myMap.get(candidate))) break; // if need only a part of keys
|
||||
}
|
||||
|
||||
@@ -38,28 +38,20 @@ public class MembershipMap<Key, Val> extends AreaMap<Key, Val> {
|
||||
}
|
||||
|
||||
public void putOptimal(final Key key, final Val val) {
|
||||
final int idx = putImpl(key, val);
|
||||
final int idx = putIfNoParent(key, val);
|
||||
if (idx < 0) return;
|
||||
|
||||
// go for parents
|
||||
for (int i = idx - 1; i >= 0; -- i) {
|
||||
if (myKeysResemblance.process(myKeys.get(i), key)) {
|
||||
consistentRemove(idx);
|
||||
return;
|
||||
if (idx + 1 < myKeys.size()) {
|
||||
for (final ListIterator<Key> listIterator = myKeys.listIterator(idx + 1); listIterator.hasNext();) {
|
||||
final Key next = listIterator.next();
|
||||
if (myKeysResemblance.process(key, next)) {
|
||||
listIterator.remove();
|
||||
myMap.remove(next);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = idx + 1; i < myKeys.size(); ++ i) {
|
||||
if (myKeysResemblance.process(key, myKeys.get(i))) {
|
||||
consistentRemove(i);
|
||||
-- i;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void consistentRemove(final int idx) {
|
||||
final Key keyToRemove = myKeys.remove(idx);
|
||||
myMap.remove(keyToRemove);
|
||||
}
|
||||
|
||||
public void optimizeMap(final PairProcessor<Val, Val> valuesAreas) {
|
||||
@@ -96,4 +88,4 @@ public class MembershipMap<Key, Val> extends AreaMap<Key, Val> {
|
||||
});
|
||||
return result.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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 com.intellij.openapi.vcs.changes;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.FilePathImpl;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author irengrig
|
||||
* Date: 2/10/11
|
||||
* Time: 3:59 PM
|
||||
*/
|
||||
abstract class AbstractIgnoredFilesHolder implements FileHolder, IgnoredFilesHolder {
|
||||
protected final Project myProject;
|
||||
private final ProjectLevelVcsManager myVcsManager;
|
||||
|
||||
protected AbstractIgnoredFilesHolder(Project project) {
|
||||
myProject = project;
|
||||
myVcsManager = ProjectLevelVcsManager.getInstance(project);
|
||||
}
|
||||
|
||||
protected abstract void removeFile(final VirtualFile file);
|
||||
protected abstract Collection<VirtualFile> keys();
|
||||
|
||||
@Override
|
||||
public void cleanAndAdjustScope(final VcsModifiableDirtyScope scope) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
if (myProject.isDisposed()) return;
|
||||
|
||||
final Iterator<VirtualFile> iterator = keys().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final VirtualFile file = iterator.next();
|
||||
if (isFileDirty(scope, file)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected boolean isFileDirty(final VcsDirtyScope scope, final VirtualFile file) {
|
||||
return fileDropped(file) || scope.belongsTo(new FilePathImpl(file));
|
||||
}
|
||||
|
||||
protected boolean fileDropped(final VirtualFile file) {
|
||||
return !file.isValid() || myVcsManager.getVcsFor(file) == null;
|
||||
}
|
||||
}
|
||||
@@ -295,7 +295,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
private void filterOutIgnoredFiles(final List<VcsDirtyScope> scopes) {
|
||||
try {
|
||||
synchronized (myDataLock) {
|
||||
final RecursiveFileHolder fileHolder = (RecursiveFileHolder)myComposite.get(FileHolder.HolderType.IGNORED);
|
||||
final IgnoredFilesHolder fileHolder = (IgnoredFilesHolder)myComposite.get(FileHolder.HolderType.IGNORED);
|
||||
|
||||
for (Iterator<VcsDirtyScope> iterator = scopes.iterator(); iterator.hasNext();) {
|
||||
final VcsModifiableDirtyScope scope = (VcsModifiableDirtyScope) iterator.next();
|
||||
@@ -337,8 +337,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
}
|
||||
|
||||
private void updateImmediately(final AtomicSectionsAware atomicSectionsAware) {
|
||||
final FileHolderComposite composite;
|
||||
final ChangeListWorker changeListWorker;
|
||||
final DataHolder dataHolder;
|
||||
|
||||
final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject);
|
||||
if (! vcsManager.hasActiveVcss()) return;
|
||||
@@ -371,43 +370,26 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
// mark for "modifier" that update started (it would create duplicates of modification commands done by user during update;
|
||||
// after update of copies of objects is complete, it would apply the same modifications to copies.)
|
||||
synchronized (myDataLock) {
|
||||
changeListWorker = myWorker.copy();
|
||||
composite = (FileHolderComposite) myComposite.copy();
|
||||
dataHolder = new DataHolder((FileHolderComposite) myComposite.copy(), myWorker.copy(), wasEverythingDirty);
|
||||
myModifier.enterUpdate();
|
||||
if (wasEverythingDirty) {
|
||||
myUpdateException = null;
|
||||
composite.cleanAll();
|
||||
}
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("refresh procedure started, everything = " + wasEverythingDirty);
|
||||
}
|
||||
}
|
||||
if (wasEverythingDirty) {
|
||||
changeListWorker.notifyStartProcessingChanges(null);
|
||||
}
|
||||
dataHolder.notifyStart();
|
||||
myChangesViewManager.scheduleRefresh();
|
||||
|
||||
final ChangeListManagerGate gate = changeListWorker.createSelfGate();
|
||||
|
||||
final ChangeListManagerGate gate = dataHolder.getChangeListWorker().createSelfGate();
|
||||
// do actual requests about file statuses
|
||||
final UpdatingChangeListBuilder builder = new UpdatingChangeListBuilder(changeListWorker, composite, new Getter<Boolean>() {
|
||||
public Boolean get() {
|
||||
return myUpdater.isStopped();
|
||||
}
|
||||
}, myIgnoredIdeaLevel, gate);
|
||||
final UpdatingChangeListBuilder builder = new UpdatingChangeListBuilder(dataHolder.getChangeListWorker(),
|
||||
dataHolder.getComposite(), myUpdater.getIsStoppedGetter(), myIgnoredIdeaLevel, gate);
|
||||
|
||||
// todo should also ask self flag
|
||||
myUpdateChangesProgressIndicator = new EmptyProgressIndicator() {
|
||||
@Override
|
||||
public boolean isCanceled() {
|
||||
return myUpdater.isStopped() || atomicSectionsAware.shouldExitAsap();
|
||||
}
|
||||
@Override
|
||||
public void checkCanceled() {
|
||||
checkIfDisposed();
|
||||
atomicSectionsAware.checkShouldExit();
|
||||
}
|
||||
};
|
||||
myUpdateChangesProgressIndicator = createProgressIndicator(atomicSectionsAware);
|
||||
|
||||
for (final VcsDirtyScope scope : scopes) {
|
||||
atomicSectionsAware.checkShouldExit();
|
||||
|
||||
@@ -416,18 +398,9 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
final VcsModifiableDirtyScope adjustedScope = vcs.adjustDirtyScope((VcsModifiableDirtyScope) scope);
|
||||
|
||||
myChangesViewManager.updateProgressText(VcsBundle.message("changes.update.progress.message", vcs.getDisplayName()), false);
|
||||
if (! wasEverythingDirty) {
|
||||
composite.cleanAndAdjustScope(adjustedScope);
|
||||
changeListWorker.notifyStartProcessingChanges(adjustedScope);
|
||||
}
|
||||
dataHolder.notifyStartProcessingChanges(adjustedScope);
|
||||
|
||||
try {
|
||||
actualUpdate(wasEverythingDirty, composite, builder, adjustedScope, vcs, changeListWorker, gate);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
LOG.debug(t);
|
||||
Rethrow.reThrowRuntime(t);
|
||||
}
|
||||
actualUpdate(builder, adjustedScope, vcs, dataHolder, gate);
|
||||
|
||||
if (myUpdateException != null) break;
|
||||
}
|
||||
@@ -435,29 +408,27 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
final boolean takeChanges = (myUpdateException == null);
|
||||
if (takeChanges) {
|
||||
// update IDEA-level ignored files
|
||||
updateIgnoredFiles(composite);
|
||||
updateIgnoredFiles(dataHolder.getComposite());
|
||||
}
|
||||
|
||||
synchronized (myDataLock) {
|
||||
// do same modifications to change lists as was done during update + do delayed notifications
|
||||
if (wasEverythingDirty) {
|
||||
changeListWorker.notifyDoneProcessingChanges(myDelayedNotificator.getProxyDispatcher());
|
||||
}
|
||||
dataHolder.notifyEnd();
|
||||
myModifier.exitUpdate();
|
||||
// should be applied for notifications to be delivered (they were delayed)
|
||||
myModifier.apply(changeListWorker);
|
||||
myModifier.apply(dataHolder.getChangeListWorker());
|
||||
myModifier.clearQueue();
|
||||
// update member from copy
|
||||
if (takeChanges) {
|
||||
myWorker.takeData(changeListWorker);
|
||||
myWorker.takeData(dataHolder.getChangeListWorker());
|
||||
}
|
||||
|
||||
if (takeChanges) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("refresh procedure finished, size: " + composite.getVFHolder(FileHolder.HolderType.UNVERSIONED).getSize());
|
||||
LOG.debug("refresh procedure finished, size: " + dataHolder.getComposite().getVFHolder(FileHolder.HolderType.UNVERSIONED).getSize());
|
||||
}
|
||||
final boolean statusChanged = ! myComposite.equals(composite);
|
||||
myComposite = composite;
|
||||
final boolean statusChanged = ! myComposite.equals(dataHolder.getComposite());
|
||||
myComposite = dataHolder.getComposite();
|
||||
if (statusChanged) {
|
||||
myDelayedNotificator.getProxyDispatcher().unchangedFileStatusChanged();
|
||||
}
|
||||
@@ -489,9 +460,71 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
}
|
||||
}
|
||||
|
||||
private void actualUpdate(final boolean wasEverythingDirty, final FileHolderComposite composite, final UpdatingChangeListBuilder builder,
|
||||
final VcsDirtyScope scope, final AbstractVcs vcs, final ChangeListWorker changeListWorker,
|
||||
final ChangeListManagerGate gate) {
|
||||
private EmptyProgressIndicator createProgressIndicator(final AtomicSectionsAware atomicSectionsAware) {
|
||||
return new EmptyProgressIndicator() {
|
||||
@Override
|
||||
public boolean isCanceled() {
|
||||
return myUpdater.isStopped() || atomicSectionsAware.shouldExitAsap();
|
||||
}
|
||||
@Override
|
||||
public void checkCanceled() {
|
||||
checkIfDisposed();
|
||||
atomicSectionsAware.checkShouldExit();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private class DataHolder {
|
||||
private final boolean myWasEverythingDirty;
|
||||
final FileHolderComposite myComposite;
|
||||
final ChangeListWorker myChangeListWorker;
|
||||
|
||||
private DataHolder(FileHolderComposite composite, ChangeListWorker changeListWorker, boolean wasEverythingDirty) {
|
||||
myComposite = composite;
|
||||
myChangeListWorker = changeListWorker;
|
||||
myWasEverythingDirty = wasEverythingDirty;
|
||||
}
|
||||
|
||||
public void notifyStart() {
|
||||
if (myWasEverythingDirty) {
|
||||
myComposite.cleanAll();
|
||||
myChangeListWorker.notifyStartProcessingChanges(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void notifyStartProcessingChanges(@NotNull final VcsModifiableDirtyScope scope) {
|
||||
if (! myWasEverythingDirty) {
|
||||
myComposite.cleanAndAdjustScope(scope);
|
||||
myChangeListWorker.notifyStartProcessingChanges(scope);
|
||||
}
|
||||
|
||||
myComposite.notifyVcsStarted(scope.getVcs());
|
||||
myChangeListWorker.notifyVcsStarted(scope.getVcs());
|
||||
}
|
||||
|
||||
public void notifyDoneProcessingChanges() {
|
||||
if (! myWasEverythingDirty) {
|
||||
myChangeListWorker.notifyDoneProcessingChanges(myDelayedNotificator.getProxyDispatcher());
|
||||
}
|
||||
}
|
||||
|
||||
public void notifyEnd() {
|
||||
if (myWasEverythingDirty) {
|
||||
myChangeListWorker.notifyDoneProcessingChanges(myDelayedNotificator.getProxyDispatcher());
|
||||
}
|
||||
}
|
||||
|
||||
public FileHolderComposite getComposite() {
|
||||
return myComposite;
|
||||
}
|
||||
|
||||
public ChangeListWorker getChangeListWorker() {
|
||||
return myChangeListWorker;
|
||||
}
|
||||
}
|
||||
|
||||
private void actualUpdate(final UpdatingChangeListBuilder builder, final VcsDirtyScope scope, final AbstractVcs vcs,
|
||||
final DataHolder dataHolder, final ChangeListManagerGate gate) {
|
||||
try {
|
||||
final ChangeProvider changeProvider = vcs.getChangeProvider();
|
||||
if (changeProvider != null) {
|
||||
@@ -507,10 +540,12 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if ((! myUpdater.isStopped()) && !wasEverythingDirty) {
|
||||
changeListWorker.notifyDoneProcessingChanges(myDelayedNotificator.getProxyDispatcher());
|
||||
} catch (Throwable t) {
|
||||
LOG.debug(t);
|
||||
Rethrow.reThrowRuntime(t);
|
||||
} finally {
|
||||
if (! myUpdater.isStopped()) {
|
||||
dataHolder.notifyDoneProcessingChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1035,7 +1070,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
|
||||
synchronized (myDataLock) {
|
||||
final VirtualFileHolder unversionedHolder = myComposite.getVFHolder(FileHolder.HolderType.UNVERSIONED);
|
||||
final RecursiveFileHolder<Object> ignoredHolder = (RecursiveFileHolder) myComposite.get(FileHolder.HolderType.IGNORED);
|
||||
final IgnoredFilesHolder ignoredHolder = (IgnoredFilesHolder) myComposite.get(FileHolder.HolderType.IGNORED);
|
||||
|
||||
scheduler.accept(unversionedHolder.getFiles());
|
||||
scheduler.accept(ignoredHolder.values());
|
||||
|
||||
@@ -531,6 +531,11 @@ public class ChangeListWorker implements ChangeListsWriteOperations {
|
||||
return myLocallyDeleted.isContainedInLocallyDeleted(filePath);
|
||||
}
|
||||
|
||||
public void notifyVcsStarted(AbstractVcs vcs) {
|
||||
myLocallyDeleted.notifyVcsStarted(vcs);
|
||||
mySwitchedHolder.notifyVcsStarted(vcs);
|
||||
}
|
||||
|
||||
private abstract class ExternalVsInternalChangesIntersection {
|
||||
protected final Collection<Change> myInChanges;
|
||||
protected final Map<Pair<String, String>, LocalChangeList> myInternalMap;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.openapi.vcs.changes;
|
||||
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -53,6 +54,10 @@ public class DeletedFilesHolder implements FileHolder {
|
||||
return HolderType.DELETED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyVcsStarted(AbstractVcs scope) {
|
||||
}
|
||||
|
||||
public void addFile(final LocallyDeletedChange change) {
|
||||
myFiles.put(change.getPresentableUrl(), change);
|
||||
}
|
||||
|
||||
@@ -15,12 +15,16 @@
|
||||
*/
|
||||
package com.intellij.openapi.vcs.changes;
|
||||
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
|
||||
interface FileHolder {
|
||||
void cleanAll();
|
||||
void cleanAndAdjustScope(VcsModifiableDirtyScope scope);
|
||||
FileHolder copy();
|
||||
HolderType getType();
|
||||
|
||||
void notifyVcsStarted(AbstractVcs scope);
|
||||
|
||||
static enum HolderType {
|
||||
DELETED,
|
||||
UNVERSIONED,
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.intellij.openapi.vcs.changes;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -29,7 +30,7 @@ public class FileHolderComposite implements FileHolder {
|
||||
myHolders.put(FileHolder.HolderType.UNVERSIONED, new VirtualFileHolder(project, FileHolder.HolderType.UNVERSIONED));
|
||||
myHolders.put(FileHolder.HolderType.ROOT_SWITCH, new SwitchedFileHolder(project, HolderType.ROOT_SWITCH));
|
||||
myHolders.put(FileHolder.HolderType.MODIFIED_WITHOUT_EDITING, new VirtualFileHolder(project, FileHolder.HolderType.MODIFIED_WITHOUT_EDITING));
|
||||
myHolders.put(FileHolder.HolderType.IGNORED, new RecursiveFileHolder<Object>(project, FileHolder.HolderType.IGNORED));
|
||||
myHolders.put(FileHolder.HolderType.IGNORED, new IgnoredFilesCompositeHolder(project));
|
||||
myHolders.put(FileHolder.HolderType.LOCKED, new VirtualFileHolder(project, FileHolder.HolderType.LOCKED));
|
||||
myHolders.put(FileHolder.HolderType.LOGICALLY_LOCKED, new LogicallyLockedHolder(project));
|
||||
}
|
||||
@@ -99,7 +100,13 @@ public class FileHolderComposite implements FileHolder {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public RecursiveFileHolder getIgnoredFileHolder() {
|
||||
return (RecursiveFileHolder) myHolders.get(HolderType.IGNORED);
|
||||
public IgnoredFilesHolder getIgnoredFileHolder() {
|
||||
return (IgnoredFilesHolder) myHolders.get(HolderType.IGNORED);
|
||||
}
|
||||
|
||||
public void notifyVcsStarted(AbstractVcs vcs) {
|
||||
for (FileHolder fileHolder : myHolders.values()) {
|
||||
fileHolder.notifyVcsStarted(vcs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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 com.intellij.openapi.vcs.changes;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author irengrig
|
||||
* Date: 2/10/11
|
||||
* Time: 3:57 PM
|
||||
*/
|
||||
public class IgnoredFilesCompositeHolder implements IgnoredFilesHolder {
|
||||
private final Map<AbstractVcs, IgnoredFilesHolder> myHolderMap;
|
||||
private final Project myProject;
|
||||
private AbstractVcs myCurrentVcs;
|
||||
private final ProjectLevelVcsManager myVcsManager;
|
||||
|
||||
public IgnoredFilesCompositeHolder(final Project project) {
|
||||
super();
|
||||
myProject = project;
|
||||
myHolderMap = new HashMap<AbstractVcs, IgnoredFilesHolder>();
|
||||
myVcsManager = ProjectLevelVcsManager.getInstance(myProject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanAll() {
|
||||
myHolderMap.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanAndAdjustScope(VcsModifiableDirtyScope scope) {
|
||||
myHolderMap.get(scope.getVcs()).cleanAndAdjustScope(scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileHolder copy() {
|
||||
final IgnoredFilesCompositeHolder result = new IgnoredFilesCompositeHolder(myProject);
|
||||
result.myHolderMap.putAll(new HashMap<AbstractVcs, IgnoredFilesHolder>(myHolderMap));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HolderType getType() {
|
||||
return HolderType.IGNORED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFile(VirtualFile file) {
|
||||
myHolderMap.get(myCurrentVcs).addFile(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsFile(VirtualFile file) {
|
||||
final AbstractVcs vcs = myVcsManager.getVcsFor(file);
|
||||
if (vcs == null) return false;
|
||||
final IgnoredFilesHolder ignoredFilesHolder = myHolderMap.get(vcs);
|
||||
return ignoredFilesHolder == null ? false : ignoredFilesHolder.containsFile(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<VirtualFile> values() {
|
||||
if (myHolderMap.size() == 1) return myHolderMap.values().iterator().next().values();
|
||||
final HashSet<VirtualFile> result = new HashSet<VirtualFile>();
|
||||
for (IgnoredFilesHolder holder : myHolderMap.values()) {
|
||||
result.addAll(holder.values());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyVcsStarted(AbstractVcs vcs) {
|
||||
myCurrentVcs = vcs;
|
||||
if (! myHolderMap.containsKey(vcs)) {
|
||||
myHolderMap.put(vcs, vcs.reportsIgnoredDirectories() ? (IgnoredFilesHolder) new RecursiveFileHolder(myProject, HolderType.IGNORED) :
|
||||
new MapIgnoredFilesHolder(myProject));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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 com.intellij.openapi.vcs.changes;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author irengrig
|
||||
* Date: 2/10/11
|
||||
* Time: 4:54 PM
|
||||
*/
|
||||
public interface IgnoredFilesHolder extends FileHolder {
|
||||
void addFile(VirtualFile file);
|
||||
boolean containsFile(VirtualFile file);
|
||||
Collection<VirtualFile> values();
|
||||
void cleanAndAdjustScope(VcsModifiableDirtyScope scope);
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.intellij.openapi.vcs.changes;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -53,6 +54,10 @@ public class LogicallyLockedHolder implements FileHolder {
|
||||
return HolderType.LOGICALLY_LOCKED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyVcsStarted(AbstractVcs vcs) {
|
||||
}
|
||||
|
||||
public boolean containsKey(final VirtualFile vf) {
|
||||
return myMap.containsKey(vf);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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 com.intellij.openapi.vcs.changes;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.hash.HashSet;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author irengrig
|
||||
* Date: 2/10/11
|
||||
* Time: 4:20 PM
|
||||
*/
|
||||
public class MapIgnoredFilesHolder extends AbstractIgnoredFilesHolder {
|
||||
private final static Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.MapIgnoredFilesHolder");
|
||||
|
||||
private final Set<VirtualFile> mySet;
|
||||
private final Project myProject;
|
||||
|
||||
public MapIgnoredFilesHolder(Project project) {
|
||||
super(project);
|
||||
myProject = project;
|
||||
mySet = new HashSet<VirtualFile>();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeFile(VirtualFile file) {
|
||||
mySet.remove(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<VirtualFile> keys() {
|
||||
return mySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFile(VirtualFile file) {
|
||||
LOG.assertTrue(! file.isDirectory());
|
||||
mySet.add(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsFile(VirtualFile file) {
|
||||
return mySet.contains(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<VirtualFile> values() {
|
||||
return mySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanAll() {
|
||||
mySet.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileHolder copy() {
|
||||
final MapIgnoredFilesHolder result = new MapIgnoredFilesHolder(myProject);
|
||||
result.mySet.addAll(mySet);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HolderType getType() {
|
||||
return HolderType.IGNORED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyVcsStarted(AbstractVcs scope) {
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ package com.intellij.openapi.vcs.changes;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diff.impl.patch.formove.FilePathComparator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vcs.FilePathImpl;
|
||||
import com.intellij.openapi.vcs.MembershipMap;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
@@ -14,84 +15,67 @@ import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.PairProcessor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class RecursiveFileHolder<T> implements FileHolder {
|
||||
public class RecursiveFileHolder<T> extends AbstractIgnoredFilesHolder {
|
||||
protected final HolderType myHolderType;
|
||||
protected final MembershipMap<VirtualFile, T> myMap;
|
||||
|
||||
protected final Project myProject;
|
||||
protected final TreeMap<VirtualFile, T> myMap;
|
||||
|
||||
public RecursiveFileHolder(final Project project, final HolderType holderType) {
|
||||
myMap = MembershipMap.createMembershipMap(new PairProcessor<VirtualFile, VirtualFile>() {
|
||||
@Override
|
||||
public boolean process(final VirtualFile parent, final VirtualFile child) {
|
||||
return VfsUtil.isAncestor(parent, child, false);
|
||||
}
|
||||
}, FilePathComparator.getInstance());
|
||||
|
||||
myProject = project;
|
||||
super(project);
|
||||
myMap = new TreeMap<VirtualFile, T>(FilePathComparator.getInstance());
|
||||
myHolderType = holderType;
|
||||
}
|
||||
|
||||
public synchronized void cleanAll() {
|
||||
public void cleanAll() {
|
||||
myMap.clear();
|
||||
}
|
||||
|
||||
public void cleanAndAdjustScope(final VcsModifiableDirtyScope scope) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
// to avoid deadlocks caused by incorrect lock ordering, need to lock on this after taking read action
|
||||
synchronized(RecursiveFileHolder.this) {
|
||||
if (myProject.isDisposed()) return;
|
||||
|
||||
final List<VirtualFile> currentFiles = new ArrayList<VirtualFile>(myMap.keySet());
|
||||
for (final VirtualFile file : currentFiles) {
|
||||
if (isFileDirty(scope, file)) {
|
||||
myMap.remove(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@Override
|
||||
protected Collection<VirtualFile> keys() {
|
||||
return myMap.keySet();
|
||||
}
|
||||
|
||||
protected boolean isFileDirty(final VcsDirtyScope scope, final VirtualFile file) {
|
||||
return fileDropped(file) || scope.belongsTo(new FilePathImpl(file));
|
||||
@Override
|
||||
public void notifyVcsStarted(AbstractVcs scope) {
|
||||
}
|
||||
|
||||
public HolderType getType() {
|
||||
return myHolderType;
|
||||
}
|
||||
|
||||
protected boolean fileDropped(final VirtualFile file) {
|
||||
return !file.isValid() || ProjectLevelVcsManager.getInstance(myProject).getVcsFor(file) == null;
|
||||
public void addFile(final VirtualFile file) {
|
||||
if (! containsFile(file)) {
|
||||
myMap.put(file, null);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void addFile(final VirtualFile file) {
|
||||
myMap.putOptimal(file, null);
|
||||
}
|
||||
|
||||
public synchronized void removeFile(final VirtualFile file) {
|
||||
public void removeFile(final VirtualFile file) {
|
||||
myMap.remove(file);
|
||||
}
|
||||
|
||||
public synchronized RecursiveFileHolder copy() {
|
||||
public RecursiveFileHolder copy() {
|
||||
final RecursiveFileHolder<T> copyHolder = new RecursiveFileHolder<T>(myProject, myHolderType);
|
||||
copyHolder.myMap.putAll(myMap);
|
||||
return copyHolder;
|
||||
}
|
||||
|
||||
public synchronized boolean containsFile(final VirtualFile file) {
|
||||
return myMap.getMapping(file) != null;
|
||||
public boolean containsFile(final VirtualFile file) {
|
||||
final VirtualFile floor = myMap.floorKey(file);
|
||||
if (floor == null) return false;
|
||||
final SortedMap<VirtualFile, T> floorMap = myMap.headMap(floor, true);
|
||||
for (VirtualFile parent : floorMap.keySet()) {
|
||||
if (VfsUtil.isAncestor(parent, file, false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public synchronized Collection<VirtualFile> values() {
|
||||
public Collection<VirtualFile> values() {
|
||||
return myMap.keySet();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.openapi.vcs.changes;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.PairProcessor;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
@@ -24,6 +25,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
|
||||
// true = recursively, branch name
|
||||
public class SwitchedFileHolder extends RecursiveFileHolder<Pair<Boolean, String>> {
|
||||
@@ -53,7 +55,7 @@ public class SwitchedFileHolder extends RecursiveFileHolder<Pair<Boolean, String
|
||||
public Map<VirtualFile, String> getFilesMapCopy() {
|
||||
final HashMap<VirtualFile, String> result = new HashMap<VirtualFile, String>();
|
||||
for (final VirtualFile vf : myMap.keySet()) {
|
||||
result.put(vf, myMap.getExact(vf).getSecond());
|
||||
result.put(vf, myMap.get(vf).getSecond());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -66,33 +68,40 @@ public class SwitchedFileHolder extends RecursiveFileHolder<Pair<Boolean, String
|
||||
public synchronized MultiMap<String, VirtualFile> getBranchToFileMap() {
|
||||
final MultiMap<String, VirtualFile> result = new MultiMap<String, VirtualFile>();
|
||||
for (final VirtualFile vf : myMap.keySet()) {
|
||||
result.putValue(myMap.getExact(vf).getSecond(), vf);
|
||||
result.putValue(myMap.get(vf).getSecond(), vf);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean containsFile(final VirtualFile file) {
|
||||
final Pair<VirtualFile, Pair<Boolean, String>> mapping = myMap.getMapping(file);
|
||||
if (mapping != null) {
|
||||
return mapping.getFirst().equals(file) || mapping.getSecond().getFirst();
|
||||
final VirtualFile floor = myMap.floorKey(file);
|
||||
if (floor == null) return false;
|
||||
final SortedMap<VirtualFile, Pair<Boolean, String>> floorMap = myMap.headMap(floor);
|
||||
for (VirtualFile parent : floorMap.keySet()) {
|
||||
if (VfsUtil.isAncestor(parent, file, false)) {
|
||||
final Pair<Boolean, String> value = floorMap.get(parent);
|
||||
return parent.equals(file) || value.getFirst();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getBranchForFile(final VirtualFile file) {
|
||||
final Pair<VirtualFile, Pair<Boolean, String>> mapping = myMap.getMapping(file);
|
||||
if (mapping != null) {
|
||||
if (mapping.getFirst().equals(file) || mapping.getSecond().getFirst()) {
|
||||
return mapping.getSecond().getSecond();
|
||||
final VirtualFile floor = myMap.floorKey(file);
|
||||
if (floor == null) return null;
|
||||
final SortedMap<VirtualFile, Pair<Boolean, String>> floorMap = myMap.headMap(floor);
|
||||
for (VirtualFile parent : floorMap.keySet()) {
|
||||
if (VfsUtil.isAncestor(parent, file, false)) {
|
||||
return floorMap.get(parent).getSecond();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void calculateChildren() {
|
||||
myMap.optimizeMap(MyOptimizeProcessor.getInstance());
|
||||
//myMap.optimizeMap(MyOptimizeProcessor.getInstance());
|
||||
}
|
||||
|
||||
private static class MyOptimizeProcessor implements PairProcessor<Pair<Boolean, String>, Pair<Boolean, String>> {
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.SomeQueue;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.io.storage.HeavyProcessLatch;
|
||||
@@ -58,6 +59,7 @@ public class UpdateRequestsQueue {
|
||||
private final ExecutorWrapper myExecutorWrapper;
|
||||
@NonNls public static final String LOCAL_CHANGES_UPDATE = "Local changes update";
|
||||
private final boolean myTrackHeavyLatch;
|
||||
private Getter<Boolean> myIsStoppedGetter;
|
||||
|
||||
public UpdateRequestsQueue(final Project project, final ScheduledExecutorService executor, final LocalChangesUpdater delegate) {
|
||||
myProject = project;
|
||||
@@ -75,6 +77,12 @@ public class UpdateRequestsQueue {
|
||||
// not initialized
|
||||
myStarted = false;
|
||||
myStopped = false;
|
||||
myIsStoppedGetter = new Getter<Boolean>() {
|
||||
@Override
|
||||
public Boolean get() {
|
||||
return isStopped();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void initialized() {
|
||||
@@ -82,6 +90,10 @@ public class UpdateRequestsQueue {
|
||||
myStarted = true;
|
||||
}
|
||||
|
||||
public Getter<Boolean> getIsStoppedGetter() {
|
||||
return myIsStoppedGetter;
|
||||
}
|
||||
|
||||
public boolean isStopped() {
|
||||
return myStopped;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.openapi.vcs.changes;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.FilePathImpl;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -42,6 +43,10 @@ public class VirtualFileHolder implements FileHolder {
|
||||
return myType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyVcsStarted(AbstractVcs vcs) {
|
||||
}
|
||||
|
||||
public void cleanAll() {
|
||||
myFiles.clear();
|
||||
myNumDirs = 0;
|
||||
|
||||
@@ -358,4 +358,9 @@ public class HgVcs extends AbstractVcs<CommittedChangeList> {
|
||||
return myExecutableValidator;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reportsIgnoredDirectories() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user