blob: 64cfb59b4df553ad1dda4456c51b2d733b1627e5 [file] [log] [blame]
/*
* Copyright 2000-2009 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.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;
import java.util.*;
/**
* @author max
*/
public class VirtualFileHolder implements FileHolder {
private final Set<VirtualFile> myFiles = new HashSet<VirtualFile>();
private final Project myProject;
private final HolderType myType;
private int myNumDirs;
public VirtualFileHolder(Project project, final HolderType type) {
myProject = project;
myType = type;
}
public HolderType getType() {
return myType;
}
@Override
public void notifyVcsStarted(AbstractVcs vcs) {
}
public void cleanAll() {
myFiles.clear();
myNumDirs = 0;
}
// returns number of removed directories
static int cleanScope(final Project project, final Collection<VirtualFile> files, final VcsModifiableDirtyScope 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;
if (scope.getRecursivelyDirtyDirectories().size() == 0) {
final Set<FilePath> dirtyFiles = scope.getDirtyFiles();
boolean cleanDroppedFiles = false;
for(FilePath dirtyFile: dirtyFiles) {
VirtualFile f = dirtyFile.getVirtualFile();
if (f != null) {
if (files.remove(f)) {
if (f.isDirectory()) ++ result;
}
}
else {
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 (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;
}
}
}
return result;
}
});
}
public void cleanAndAdjustScope(final VcsModifiableDirtyScope scope) {
myNumDirs -= cleanScope(myProject, myFiles, scope);
}
private static boolean fileDropped(final VirtualFile file) {
return ! file.isValid();
}
public void addFile(VirtualFile file) {
myFiles.add(file);
if (file.isDirectory()) ++ myNumDirs;
}
public void removeFile(VirtualFile file) {
if (myFiles.remove(file)) {
if (file.isDirectory()) {
-- myNumDirs;
}
}
}
// todo track number of copies made
public List<VirtualFile> getFiles() {
return new ArrayList<VirtualFile>(myFiles);
}
public VirtualFileHolder copy() {
final VirtualFileHolder copyHolder = new VirtualFileHolder(myProject, myType);
copyHolder.myFiles.addAll(myFiles);
copyHolder.myNumDirs = myNumDirs;
return copyHolder;
}
public boolean containsFile(final VirtualFile file) {
return myFiles.contains(file);
}
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final VirtualFileHolder that = (VirtualFileHolder)o;
if (!myFiles.equals(that.myFiles)) return false;
return true;
}
public int hashCode() {
return myFiles.hashCode();
}
public int getSize() {
return myFiles.size();
}
public int getNumDirs() {
assert myNumDirs >= 0;
return myNumDirs;
}
}