VCS: ignored & unversioned as-is; test for external changes detection - initial version; heavy latch aware for local changes gathering: through -D

This commit is contained in:
irengrig
2010-10-06 01:47:51 +04:00
parent b46669f89a
commit 6f261bceb6
16 changed files with 166 additions and 131 deletions
@@ -82,11 +82,6 @@ public class MockChangelistBuilder implements ChangelistBuilder {
public void processRootSwitch(VirtualFile file, String branch) {
}
@Override
public boolean isUpdatingUnversionedFiles() {
return true;
}
@Override
public boolean reportChangesOutsideProject() {
return false;
@@ -134,4 +134,24 @@ public class AreaMap<Key, Val> {
myKeys.clear();
myMap.clear();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AreaMap areaMap = (AreaMap)o;
if (!myKeys.equals(areaMap.myKeys)) return false;
if (!myMap.equals(areaMap.myMap)) return false;
return true;
}
@Override
public int hashCode() {
int result = myKeys.hashCode();
result = 31 * result + myMap.hashCode();
return result;
}
}
@@ -105,7 +105,5 @@ public interface ChangelistBuilder {
void processRootSwitch(VirtualFile file, String branch);
boolean isUpdatingUnversionedFiles();
boolean reportChangesOutsideProject();
}
@@ -61,10 +61,6 @@ public class EmptyChangelistBuilder implements ChangelistBuilder {
public void processRootSwitch(VirtualFile file, String branch) {
}
public boolean isUpdatingUnversionedFiles() {
return true;
}
public boolean reportChangesOutsideProject() {
return false;
}
@@ -263,20 +263,20 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
static class DisposedException extends RuntimeException {}
public void scheduleUpdate() {
myUpdater.schedule(true);
myUpdater.schedule();
}
public void scheduleUpdate(boolean updateUnversionedFiles) {
myUpdater.schedule(updateUnversionedFiles);
myUpdater.schedule();
}
private class ActualUpdater implements LocalChangesUpdater {
public void execute(boolean updateUnversioned, AtomicSectionsAware atomicSectionsAware) {
updateImmediately(updateUnversioned, atomicSectionsAware);
public void execute(AtomicSectionsAware atomicSectionsAware) {
updateImmediately(atomicSectionsAware);
}
}
private void updateImmediately(final boolean updateUnversionedFiles, final AtomicSectionsAware atomicSectionsAware) {
private void updateImmediately(final AtomicSectionsAware atomicSectionsAware) {
FileHolderComposite composite;
ChangeListWorker changeListWorker;
@@ -313,13 +313,11 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
// after update of copies of objects is complete, it would apply the same modifications to copies.)
synchronized (myDataLock) {
changeListWorker = myWorker.copy();
composite = updateUnversionedFiles ? (FileHolderComposite) myComposite.copy() : myComposite;
composite = (FileHolderComposite) myComposite.copy();
myModifier.enterUpdate();
if (wasEverythingDirty) {
myUpdateException = null;
}
if (updateUnversionedFiles && wasEverythingDirty) {
composite.cleanAll();
composite.cleanAll();
}
}
if (wasEverythingDirty) {
@@ -334,7 +332,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
public Boolean get() {
return myUpdater.isStopped();
}
}, updateUnversionedFiles, myIgnoredIdeaLevel, gate);
}, myIgnoredIdeaLevel, gate);
myUpdateChangesProgressIndicator = new EmptyProgressIndicator() {
@Override
@@ -356,29 +354,26 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
myChangesViewManager.updateProgressText(VcsBundle.message("changes.update.progress.message", vcs.getDisplayName()), false);
if (! wasEverythingDirty) {
composite.cleanAndAdjustScope(adjustedScope);
changeListWorker.notifyStartProcessingChanges(adjustedScope);
}
if (updateUnversionedFiles && !wasEverythingDirty) {
composite.cleanScope(adjustedScope);
}
try {
actualUpdate(wasEverythingDirty, composite, builder, adjustedScope, vcs, changeListWorker, gate);
}
catch (Throwable t) {
LOG.info(t);
if (t instanceof Error) {
throw (Error) t;
} else if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
throw new RuntimeException(t);
reThrowRuntime(t);
}
if (myUpdateException != null) break;
}
final boolean takeChanges = (myUpdateException == null);
if (takeChanges) {
// update IDEA-level ignored files
updateIgnoredFiles(composite);
}
synchronized (myDataLock) {
// do same modifications to change lists as was done during update + do delayed notifications
@@ -394,17 +389,13 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
myWorker.takeData(changeListWorker);
}
if (takeChanges && updateUnversionedFiles) {
boolean statusChanged = !myComposite.equals(composite);
if (takeChanges) {
final boolean statusChanged = ! myComposite.equals(composite);
myComposite = composite;
if (statusChanged) {
myDelayedNotificator.getProxyDispatcher().unchangedFileStatusChanged();
}
}
if (takeChanges) {
updateIgnoredFiles(false);
}
myShowLocalChangesInvalidated = false;
}
myChangesViewManager.scheduleRefresh();
@@ -431,6 +422,15 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
}
}
private static void reThrowRuntime(final Throwable t) {
if (t instanceof Error) {
throw (Error) t;
} else if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
throw new RuntimeException(t);
}
private void actualUpdate(final boolean wasEverythingDirty, final FileHolderComposite composite, final UpdatingChangeListBuilder builder,
final VcsDirtyScope scope, final AbstractVcs vcs, final ChangeListWorker changeListWorker,
final ChangeListManagerGate gate) {
@@ -499,35 +499,49 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
}
public List<VirtualFile> getUnversionedFiles() {
return myComposite.getVFHolder(FileHolder.HolderType.UNVERSIONED).getFiles();
synchronized (myDataLock) {
return myComposite.getVFHolder(FileHolder.HolderType.UNVERSIONED).getFiles();
}
}
Pair<Integer, Integer> getUnversionedFilesSize() {
final VirtualFileHolder holder = myComposite.getVFHolder(FileHolder.HolderType.UNVERSIONED);
return new Pair<Integer, Integer>(holder.getSize(), holder.getNumDirs());
synchronized (myDataLock) {
final VirtualFileHolder holder = myComposite.getVFHolder(FileHolder.HolderType.UNVERSIONED);
return new Pair<Integer, Integer>(holder.getSize(), holder.getNumDirs());
}
}
List<VirtualFile> getModifiedWithoutEditing() {
return new ArrayList<VirtualFile>(myComposite.getVFHolder(FileHolder.HolderType.MODIFIED_WITHOUT_EDITING).getFiles());
synchronized (myDataLock) {
return myComposite.getVFHolder(FileHolder.HolderType.MODIFIED_WITHOUT_EDITING).getFiles();
}
}
/**
* @return only roots for ignored folders, and ignored files
*/
List<VirtualFile> getIgnoredFiles() {
return new ArrayList<VirtualFile>(myComposite.getIgnoredFileHolder().values());
synchronized (myDataLock) {
return new ArrayList<VirtualFile>(myComposite.getIgnoredFileHolder().values());
}
}
public List<VirtualFile> getLockedFolders() {
return new ArrayList<VirtualFile>(myComposite.getVFHolder(FileHolder.HolderType.LOCKED).getFiles());
synchronized (myDataLock) {
return myComposite.getVFHolder(FileHolder.HolderType.LOCKED).getFiles();
}
}
Map<VirtualFile, LogicalLock> getLogicallyLockedFolders() {
return new HashMap<VirtualFile, LogicalLock>(((LogicallyLockedHolder) myComposite.get(FileHolder.HolderType.LOGICALLY_LOCKED)).getMap());
synchronized (myDataLock) {
return new HashMap<VirtualFile, LogicalLock>(((LogicallyLockedHolder) myComposite.get(FileHolder.HolderType.LOGICALLY_LOCKED)).getMap());
}
}
public boolean isLogicallyLocked(final VirtualFile file) {
return ((LogicallyLockedHolder) myComposite.get(FileHolder.HolderType.LOGICALLY_LOCKED)).getMap().containsKey(file);
synchronized (myDataLock) {
return ((LogicallyLockedHolder) myComposite.get(FileHolder.HolderType.LOGICALLY_LOCKED)).containsKey(file);
}
}
public boolean isContainedInLocallyDeleted(final FilePath filePath) {
@@ -732,7 +746,9 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
}
public boolean isUnversioned(VirtualFile file) {
return myComposite.getVFHolder(FileHolder.HolderType.UNVERSIONED).containsFile(file);
synchronized (myDataLock) {
return myComposite.getVFHolder(FileHolder.HolderType.UNVERSIONED).containsFile(file);
}
}
@NotNull
@@ -912,39 +928,21 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
public void addFilesToIgnore(final IgnoredFileBean... filesToIgnore) {
myIgnoredIdeaLevel.add(filesToIgnore);
updateIgnoredFiles(true);
scheduleUpdate();
}
public void setFilesToIgnore(final IgnoredFileBean... filesToIgnore) {
myIgnoredIdeaLevel.set(filesToIgnore);
// todo!!!!!! dont synchronously
updateIgnoredFiles(true);
scheduleUpdate();
}
private void updateIgnoredFiles(final boolean checkIgnored) {
synchronized (myDataLock) {
List<VirtualFile> unversionedFiles = myComposite.getVFHolder(FileHolder.HolderType.UNVERSIONED).getFiles();
//List<VirtualFile> ignoredFiles = myComposite.getVFHolder(FileHolder.HolderType.IGNORED).getFiles();
boolean somethingChanged = false;
for(VirtualFile file: unversionedFiles) {
if (isIgnoredFile(file)) {
somethingChanged = true;
myComposite.getVFHolder(FileHolder.HolderType.UNVERSIONED).removeFile(file);
myComposite.getIgnoredFileHolder().addFile(file);
}
}
/*if (checkIgnored) {
for(VirtualFile file: ignoredFiles) {
if (!isIgnoredFile(file)) {
somethingChanged = true;
// the file may have been reported as ignored by the VCS, so we can't directly move it to unversioned files
VcsDirtyScopeManager.getInstance(myProject).fileDirty(file);
}
}
}*/
if (somethingChanged) {
myFileStatusManager.fileStatusesChanged();
myChangesViewManager.scheduleRefresh();
private void updateIgnoredFiles(final FileHolderComposite composite) {
List<VirtualFile> unversionedFiles = composite.getVFHolder(FileHolder.HolderType.UNVERSIONED).getFiles();
for(VirtualFile file: unversionedFiles) {
if (isIgnoredFile(file)) {
composite.getVFHolder(FileHolder.HolderType.UNVERSIONED).removeFile(file);
composite.getIgnoredFileHolder().addFile(file);
}
}
}
@@ -370,8 +370,8 @@ public class ChangeListWorker implements ChangeListsWriteOperations {
// scope should be modified for correct moves tracking
correctScopeForMoves(scope, oldChanges);
myLocallyDeleted.cleanScope(scope);
mySwitchedHolder.cleanScope(scope);
myLocallyDeleted.cleanAndAdjustScope(scope);
mySwitchedHolder.cleanAndAdjustScope(scope);
}
private void correctScopeForMoves(final VcsAppendableDirtyScope scope, final Collection<Change> changes) {
@@ -37,7 +37,7 @@ public class DeletedFilesHolder implements FileHolder {
myFiles.putAll(holder.myFiles);
}
public void cleanScope(final VcsDirtyScope scope) {
public void cleanAndAdjustScope(final VcsAppendableDirtyScope scope) {
if (scope == null) {
myFiles.clear();
}
@@ -17,7 +17,7 @@ package com.intellij.openapi.vcs.changes;
interface FileHolder {
void cleanAll();
void cleanScope(VcsDirtyScope scope);
void cleanAndAdjustScope(VcsAppendableDirtyScope scope);
FileHolder copy();
HolderType getType();
@@ -53,9 +53,9 @@ public class FileHolderComposite implements FileHolder {
}
}
public void cleanScope(final VcsDirtyScope scope) {
public void cleanAndAdjustScope(final VcsAppendableDirtyScope scope) {
for (FileHolder holder : myHolders.values()) {
holder.cleanScope(scope);
holder.cleanAndAdjustScope(scope);
}
}
@@ -18,5 +18,5 @@ package com.intellij.openapi.vcs.changes;
import com.intellij.lifecycle.AtomicSectionsAware;
public interface LocalChangesUpdater {
void execute(boolean updateUnversioned, AtomicSectionsAware atomicSectionsAware);
void execute(AtomicSectionsAware atomicSectionsAware);
}
@@ -18,6 +18,7 @@ package com.intellij.openapi.vcs.changes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -38,7 +39,7 @@ public class LogicallyLockedHolder implements FileHolder {
myMap.put(file, lock);
}
public void cleanScope(VcsDirtyScope scope) {
public void cleanAndAdjustScope(VcsAppendableDirtyScope scope) {
VirtualFileHolder.cleanScope(myProject, myMap.keySet(), scope);
}
@@ -52,7 +53,28 @@ public class LogicallyLockedHolder implements FileHolder {
return HolderType.LOGICALLY_LOCKED;
}
public boolean containsKey(final VirtualFile vf) {
return myMap.containsKey(vf);
}
public Map<VirtualFile, LogicalLock> getMap() {
return myMap;
return Collections.unmodifiableMap(myMap);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
LogicallyLockedHolder that = (LogicallyLockedHolder)o;
if (!myMap.equals(that.myMap)) return false;
return true;
}
@Override
public int hashCode() {
return myMap.hashCode();
}
}
@@ -43,7 +43,7 @@ public class RecursiveFileHolder<T> implements FileHolder {
myMap.clear();
}
public void cleanScope(final VcsDirtyScope scope) {
public void cleanAndAdjustScope(final VcsAppendableDirtyScope 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
@@ -94,4 +94,19 @@ public class RecursiveFileHolder<T> implements FileHolder {
public synchronized Collection<VirtualFile> values() {
return myMap.keySet();
}
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final RecursiveFileHolder that = (RecursiveFileHolder)o;
if (!myMap.equals(that.myMap)) return false;
return true;
}
public int hashCode() {
return myMap.hashCode();
}
}
@@ -25,6 +25,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.util.Consumer;
import com.intellij.util.io.storage.HeavyProcessLatch;
import org.jetbrains.annotations.NonNls;
import javax.swing.*;
@@ -41,6 +42,7 @@ import java.util.concurrent.TimeUnit;
@SomeQueue
public class UpdateRequestsQueue {
private final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.UpdateRequestsQueue");
private final static String ourHeavyLatchOptimization = "vcs.local.changes.track.heavy.latch";
private final Project myProject;
private final ScheduledExecutorService myExecutor;
private final LocalChangesUpdater myDelegate;
@@ -51,15 +53,16 @@ public class UpdateRequestsQueue {
private boolean myRequestSubmitted;
private final List<Runnable> myWaitingUpdateCompletionQueue;
private final ProjectLevelVcsManager myPlVcsManager;
private boolean myUpdateUnversionedRequested;
//private final ScheduledSlowlyClosingAlarm mySharedExecutor;
private final StartupManager myStartupManager;
private final ExecutorWrapper myExecutorWrapper;
@NonNls public static final String LOCAL_CHANGES_UPDATE = "Local changes update";
private final boolean myTrackHeavyLatch;
public UpdateRequestsQueue(final Project project, final ScheduledExecutorService executor, final LocalChangesUpdater delegate) {
myProject = project;
myExecutor = executor;
myTrackHeavyLatch = Boolean.parseBoolean(System.getProperty(ourHeavyLatchOptimization));
//mySharedExecutor = ControlledAlarmFactory.createScheduledOnSharedThread(project, LOCAL_CHANGES_UPDATE, executor);
myExecutorWrapper = new ExecutorWrapper(myProject, LOCAL_CHANGES_UPDATE);
@@ -72,7 +75,6 @@ public class UpdateRequestsQueue {
// not initialized
myStarted = false;
myStopped = false;
myUpdateUnversionedRequested = false;
}
public void initialized() {
@@ -84,7 +86,7 @@ public class UpdateRequestsQueue {
return myStopped;
}
public void schedule(final boolean updateUnversionedFiles) {
public void schedule() {
synchronized (myLock) {
if (! myStarted && ApplicationManager.getApplication().isUnitTestMode()) return;
@@ -94,9 +96,6 @@ public class UpdateRequestsQueue {
myRequestSubmitted = true;
myExecutor.schedule(runnable, 300, TimeUnit.MILLISECONDS);
LOG.debug("Scheduled for project: " + myProject.getName() + ", runnable: " + runnable.hashCode());
myUpdateUnversionedRequested |= updateUnversionedFiles;
} else if (updateUnversionedFiles && (! myUpdateUnversionedRequested)) {
myUpdateUnversionedRequested = true;
}
}
}
@@ -136,7 +135,7 @@ public class UpdateRequestsQueue {
}
myWaitingUpdateCompletionQueue.add(data.getCallback());
schedule(true);
schedule();
}
}
// do not run under lock; stopped cannot be switched into not stopped - can check without lock
@@ -165,11 +164,11 @@ public class UpdateRequestsQueue {
try {
synchronized (myLock) {
if ((! myStopped) && ((! myStarted) || myPlVcsManager.isBackgroundVcsOperationRunning()) ||
(! ((StartupManagerImpl) myStartupManager).startupActivityPassed())) {
(! ((StartupManagerImpl) myStartupManager).startupActivityPassed()) || myTrackHeavyLatch && HeavyProcessLatch.INSTANCE.isRunning()) {
LOG.debug("MyRunnable: not started, not stopped, reschedule, project: " + myProject.getName() + ", runnable: " + hashCode());
myRequestSubmitted = false;
// try again after time
schedule(myUpdateUnversionedRequested);
schedule();
return;
}
@@ -180,17 +179,12 @@ public class UpdateRequestsQueue {
LOG.debug("MyRunnable: STOPPED, project: " + myProject.getName() + ", runnable: " + hashCode());
return;
}
// take it under lock
updateUnversioned = myUpdateUnversionedRequested;
// for concurrent schedules to tigger flag correctly
myUpdateUnversionedRequested = false;
}
LOG.debug("MyRunnable: INVOKE, project: " + myProject.getName() + ", runnable: " + hashCode());
myExecutorWrapper.submit(new Consumer<AtomicSectionsAware>() {
public void consume(AtomicSectionsAware atomicSectionsAware) {
myDelegate.execute(updateUnversioned, atomicSectionsAware);
myDelegate.execute(atomicSectionsAware);
}
});
LOG.debug("MyRunnable: invokeD, project: " + myProject.getName() + ", runnable: " + hashCode());
@@ -34,7 +34,6 @@ class UpdatingChangeListBuilder implements ChangelistBuilder {
private final Getter<Boolean> myDisposedGetter;
private VcsDirtyScope myScope;
private FoldersCutDownWorker myFoldersCutDownWorker;
private final boolean myUpdateUnversioned;
private final IgnoredFilesComponent myIgnoredFilesComponent;
private final ExcludedFileIndex myIndex;
private final ChangeListManagerGate myGate;
@@ -42,12 +41,10 @@ class UpdatingChangeListBuilder implements ChangelistBuilder {
UpdatingChangeListBuilder(final ChangeListWorker changeListWorker,
final FileHolderComposite composite,
final Getter<Boolean> disposedGetter,
final boolean updateUnversioned,
final IgnoredFilesComponent ignoredFilesComponent, final ChangeListManagerGate gate) {
myChangeListWorker = changeListWorker;
myComposite = composite;
myDisposedGetter = disposedGetter;
myUpdateUnversioned = updateUnversioned;
myIgnoredFilesComponent = ignoredFilesComponent;
myGate = gate;
myIndex = ExcludedFileIndex.getInstance(changeListWorker.getProject());
@@ -112,7 +109,7 @@ class UpdatingChangeListBuilder implements ChangelistBuilder {
}
public void processUnversionedFile(final VirtualFile file) {
if (file == null || ! myUpdateUnversioned) return;
if (file == null) return;
checkIfDisposed();
if (isExcluded(file)) return;
if (myScope.belongsTo(new FilePathImpl(file))) {
@@ -134,7 +131,6 @@ class UpdatingChangeListBuilder implements ChangelistBuilder {
}
public void processLocallyDeletedFile(LocallyDeletedChange locallyDeletedChange) {
if (! myUpdateUnversioned) return;
checkIfDisposed();
final FilePath file = locallyDeletedChange.getPath();
if (FileTypeManager.getInstance().isFileIgnored(file.getName())) return;
@@ -144,7 +140,7 @@ class UpdatingChangeListBuilder implements ChangelistBuilder {
}
public void processModifiedWithoutCheckout(final VirtualFile file) {
if (file == null || ! myUpdateUnversioned) return;
if (file == null) return;
checkIfDisposed();
if (isExcluded(file)) return;
if (myScope.belongsTo(new FilePathImpl(file))) {
@@ -153,7 +149,7 @@ class UpdatingChangeListBuilder implements ChangelistBuilder {
}
public void processIgnoredFile(final VirtualFile file) {
if (file == null || ! myUpdateUnversioned) return;
if (file == null) return;
checkIfDisposed();
if (isExcluded(file)) return;
if (myScope.belongsTo(new FilePathImpl(file))) {
@@ -180,7 +176,7 @@ class UpdatingChangeListBuilder implements ChangelistBuilder {
}
public void processSwitchedFile(final VirtualFile file, final String branch, final boolean recursive) {
if (file == null || ! myUpdateUnversioned) return;
if (file == null) return;
checkIfDisposed();
if (isExcluded(file)) return;
if (myScope.belongsTo(new FilePathImpl(file))) {
@@ -196,10 +192,6 @@ class UpdatingChangeListBuilder implements ChangelistBuilder {
}
}
public boolean isUpdatingUnversionedFiles() {
return myUpdateUnversioned;
}
public boolean reportChangesOutsideProject() {
return false;
}
@@ -20,7 +20,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.FilePathImpl;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vfs.VirtualFile;
import java.util.*;
@@ -49,16 +48,17 @@ public class VirtualFileHolder implements FileHolder {
}
// returns number of removed directories
static int cleanScope(final Project project, final Collection<VirtualFile> files, final VcsDirtyScope scope) {
static int cleanScope(final Project project, final Collection<VirtualFile> files, final VcsAppendableDirtyScope scope) {
return ApplicationManager.getApplication().runReadAction(new Computable<Integer>() {
public Integer compute() {
int result = 0;
// to avoid deadlocks caused by incorrect lock ordering, need to lock on this after taking read action
if (project.isDisposed() || files.isEmpty()) return 0;
final List<VirtualFile> currentFiles = new ArrayList<VirtualFile>(files);
if (scope.getRecursivelyDirtyDirectories().size() == 0) {
final Set<FilePath> dirtyFiles = scope.getDirtyFiles();
boolean cleanedDroppedFiles = false;
boolean cleanDroppedFiles = false;
for(FilePath dirtyFile: dirtyFiles) {
VirtualFile f = dirtyFile.getVirtualFile();
if (f != null) {
@@ -66,22 +66,30 @@ public class VirtualFileHolder implements FileHolder {
if (f.isDirectory()) ++ result;
}
else {
if (!cleanedDroppedFiles) {
cleanedDroppedFiles = true;
for(VirtualFile file: currentFiles) {
if (fileDropped(project, file)) {
files.remove(file);
if (file.isDirectory()) ++ result;
}
cleanDroppedFiles = true;
}
if (cleanDroppedFiles) {
for (Iterator<VirtualFile> iterator = files.iterator(); iterator.hasNext();) {
final VirtualFile file = iterator.next();
if (fileDropped(file)) {
iterator.remove();
scope.addDirtyFile(new FilePathImpl(file));
if (file.isDirectory()) ++ result;
}
}
}
}
}
else {
for (VirtualFile file : currentFiles) {
if (fileDropped(project, file) || scope.belongsTo(new FilePathImpl(file))) {
files.remove(file);
for (Iterator<VirtualFile> iterator = files.iterator(); iterator.hasNext();) {
final VirtualFile file = iterator.next();
final boolean fileDropped = fileDropped(file);
if (fileDropped) {
scope.addDirtyFile(new FilePathImpl(file));
}
if (fileDropped || scope.belongsTo(new FilePathImpl(file))) {
iterator.remove();
if (file.isDirectory()) ++ result;
}
}
@@ -91,12 +99,12 @@ public class VirtualFileHolder implements FileHolder {
});
}
public void cleanScope(final VcsDirtyScope scope) {
public void cleanAndAdjustScope(final VcsAppendableDirtyScope scope) {
myNumDirs -= cleanScope(myProject, myFiles, scope);
}
private static boolean fileDropped(final Project project, final VirtualFile file) {
return !file.isValid() || ProjectLevelVcsManager.getInstance(project).getVcsFor(file) == null;
private static boolean fileDropped(final VirtualFile file) {
return ! file.isValid();
}
public void addFile(VirtualFile file) {
@@ -109,6 +117,7 @@ public class VirtualFileHolder implements FileHolder {
if (file.isDirectory()) -- myNumDirs;
}
// todo track number of copies made
public List<VirtualFile> getFiles() {
return new ArrayList<VirtualFile>(myFiles);
}
@@ -126,10 +126,6 @@ public class GatheringChangelistBuilder implements ChangelistBuilder {
public void processRootSwitch(VirtualFile file, String branch) {
}
public boolean isUpdatingUnversionedFiles() {
return false;
}
public boolean reportChangesOutsideProject() {
return true;
}