optimisation: way to get file boolean attributes in batch

This commit is contained in:
Alexey Kudravtsev
2012-01-30 10:21:18 +04:00
parent 9f3ca33757
commit 44ff949588
13 changed files with 239 additions and 90 deletions
@@ -215,11 +215,12 @@ public class PsiDirectoryImpl extends PsiElementBase implements PsiDirectory, Qu
ProgressIndicatorProvider.checkCanceled();
for (VirtualFile vFile : myFile.getChildren()) {
boolean isDir = vFile.isDirectory();
if (processor instanceof PsiFileSystemItemProcessor &&
!((PsiFileSystemItemProcessor)processor).acceptItem(vFile.getName(), vFile.isDirectory())) {
!((PsiFileSystemItemProcessor)processor).acceptItem(vFile.getName(), isDir)) {
continue;
}
if (vFile.isDirectory()) {
if (isDir) {
PsiDirectory dir = myManager.findDirectory(vFile);
if (dir != null) {
if (!processor.execute(dir)) return false;
@@ -23,6 +23,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileListener;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.VirtualFileSystem;
import org.intellij.lang.annotations.MagicConstant;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -103,4 +104,48 @@ public abstract class NewVirtualFileSystem extends VirtualFileSystem implements
public String getCanonicallyCasedName(@NotNull VirtualFile file) {
return file.getName();
}
public static final int BA_EXISTS = 0x01;
public static final int BA_REGULAR = 0x02;
public static final int BA_DIRECTORY = 0x04;
public static final int BA_HIDDEN = 0x08;
@MagicConstant(flags = {BA_EXISTS, BA_REGULAR, BA_DIRECTORY, BA_HIDDEN})
public @interface FileBooleanAttributes {}
/**
* Queries the file about several attributes at once, and returns them ORed together.
* This method is typically faster than several methods calls querying corresponding file attributes one by one.
*
* @param file to query.
* @param flags Attributes to query the file for.
* Each attribute is an int constant from this class.
* Following attributes are defined:
* <ul>
* <li>{@link #BA_EXISTS} is set if {@link java.io.File#exists()} returns true</li>
* <li>{@link #BA_DIRECTORY} is set if {@link java.io.File#isDirectory()} returns true</li>
* <li>{@link #BA_HIDDEN} is set if {@link java.io.File#isHidden()} returns true</li>
* <li>{@link #BA_REGULAR} is set if {@link java.io.File#isFile()} returns true</li>
* </ul>
* Attributes can be bitwise ORed together to query several file attributes at once.
* <code>-1</code> as an argument value will query all attributes.
* @return Attributes mask for the file, where the bit is set if the corresponding attribute for the file is true.
* That is, the return value is <pre>{@code
* (file.exists() ? BA_EXISTS : 0) |
* (file.isDirectory()() ? BA_DIRECTORY : 0) |
* (file.isRegular()() ? BA_REGULAR : 0) |
* (file.isHidden()() ? BA_HIDDEN : 0)
* }</pre>
* Except that the bit in the return value is undefined if the corresponding bit in the flags parameter is not set.
* <p>
* Example usage:
* <pre>{@code
* int attributes = getBooleanAttributes(file, BA_EXISTS | BA_DIRECTORY);
* if ((attributes & BA_EXISTS) != 0) {
* // file exists
* boolean isDirectory = (attributes & BA_DIRECTORY) != 0;
* }}</pre>
*/
@FileBooleanAttributes
public abstract int getBooleanAttributes(@NotNull final VirtualFile file, @FileBooleanAttributes int flags);
}
@@ -270,7 +270,7 @@ public class TempFileSystem extends NewVirtualFileSystem {
}
}
private static abstract class FSItem {
private abstract static class FSItem {
private final FSDir myParent;
private String myName;
private long myTimestamp;
@@ -365,4 +365,13 @@ public class TempFileSystem extends NewVirtualFileSystem {
return false;
}
}
@Override
public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
FSItem item = convert(file);
int isDir = item instanceof FSDir ? BA_DIRECTORY : 0;
int exists = item == null ? 0 : BA_EXISTS;
int regular = isDir == 0 ? BA_REGULAR : 0;
return isDir | exists | regular;
}
}
@@ -365,4 +365,22 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo
public VirtualFile refreshAndFindFileByPath(@NotNull String path) {
return VfsImplUtil.refreshAndFindFileByPath(this, path);
}
@Override
public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
int exists = 0;
JarHandler handler = getHandler(file);
if ((flags & BA_EXISTS) != 0) {
exists = handler.exists(file) ? BA_EXISTS : 0;
}
int isDir = 0;
if ((flags & BA_DIRECTORY) != 0) {
isDir = handler.isDirectory(file) ? BA_DIRECTORY : 0;
}
int regular = 0;
if ((flags & BA_REGULAR) != 0) {
regular = isDir == 0 ? BA_REGULAR : 0;
}
return exists | isDir | regular;
}
}
@@ -25,10 +25,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.*;
import com.intellij.openapi.vfs.ex.VirtualFileManagerEx;
import com.intellij.openapi.vfs.newvfs.ManagingFS;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.openapi.vfs.newvfs.RefreshQueue;
import com.intellij.openapi.vfs.newvfs.VfsImplUtil;
import com.intellij.openapi.vfs.newvfs.*;
import com.intellij.openapi.vfs.newvfs.impl.FakeVirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Processor;
@@ -140,10 +137,6 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
private static final Method JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD;
private static final Object/* java.io.FileSystem */ JAVA_IO_FILESYSTEM;
// copied from FileSystem
private static final int BA_EXISTS = 0x01;
private static final int BA_REGULAR = 0x02;
private static final int BA_DIRECTORY = 0x04;
private static final int BA_HIDDEN = 0x08;
static {
Object fs;
@@ -170,6 +163,8 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD = getBooleanAttributes;
}
@NotNull
private static File convertToIOFileAndCheck(@NotNull final VirtualFile file) throws FileNotFoundException {
final File ioFile = convertToIOFile(file);
@@ -769,6 +764,17 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
}
}
@Override
public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
int attributes = getBooleanAttributes(convertToIOFile(file));
if (attributes != -1) return attributes & flags;
return ((flags & BA_EXISTS) != 0 && exists(file) ? BA_EXISTS : 0) |
((flags & BA_DIRECTORY) != 0 && isDirectory(file) ? BA_DIRECTORY : 0) |
((flags & BA_REGULAR) != 0 && !isSpecialFile(file) ? BA_REGULAR : 0) |
((flags & BA_HIDDEN) != 0 && convertToIOFile(file).isHidden() ? BA_HIDDEN : 0)
;
}
@Override
public void refresh(final boolean asynchronous) {
RefreshQueue.getInstance().refresh(asynchronous, true, null, ManagingFS.getInstance().getRoots(this));
@@ -15,23 +15,28 @@
*/
package com.intellij.openapi.vfs.impl.win32;
import org.intellij.lang.annotations.MagicConstant;
/**
* @author Dmitry Avdeev
*/
public class FileInfo {
static {
initIDs();
}
static {
initIDs();
}
private static native void initIDs();
public String name;
public int attributes;
public long timestamp;
public long length;
private static native void initIDs();
public String toString() {
return name;
}
public String name;
@MagicConstant(flagsFromClass = Win32Kernel.class)
public int attributes;
public long timestamp;
public long length;
public String toString() {
return name;
}
}
@@ -15,7 +15,10 @@
*/
package com.intellij.openapi.vfs.impl.win32;
import com.intellij.openapi.vfs.newvfs.NewVirtualFileSystem;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.FileNotFoundException;
import java.util.ArrayList;
@@ -27,7 +30,10 @@ import java.util.Map;
*/
public class Win32Kernel {
public static final int FILE_ATTRIBUTE_READONLY = 0x0001;
public static final int FILE_ATTRIBUTE_HIDDEN = 0x0002;
public static final int FILE_ATTRIBUTE_DIRECTORY = 0x0010;
public static final int FILE_ATTRIBUTE_DEVICE = 0x0040;
public static final int FILE_ATTRIBUTE_REPARSE_POINT = 0x0400;
private final IdeaWin32 myKernel = new IdeaWin32();
@@ -43,13 +49,12 @@ public class Win32Kernel {
return ArrayUtil.EMPTY_STRING_ARRAY;
}
ArrayList<String> names = new ArrayList<String>(fileInfos.length);
for (int i = 0, fileInfosLength = fileInfos.length; i < fileInfosLength; i++) {
FileInfo info = fileInfos[i];
for (FileInfo info : fileInfos) {
if (info.name.equals(".")) {
myCache.put(absolutePath, info);
continue;
}
else if (info.name.equals("..")) {
if (info.name.equals("..")) {
continue;
}
myCache.put(absolutePath + "/" + info.name, info);
@@ -59,8 +64,8 @@ public class Win32Kernel {
return ArrayUtil.toStringArray(names);
}
public void exists(String path) throws FileNotFoundException {
getInfo(path);
public boolean exists(String path) {
return doGetInfo(path) != null;
}
public boolean isDirectory(String path) throws FileNotFoundException {
@@ -84,14 +89,42 @@ public class Win32Kernel {
}
private FileInfo getInfo(String path) throws FileNotFoundException {
FileInfo info = doGetInfo(path);
if (info == null) {
throw new FileNotFoundException(path);
}
return info;
}
@Nullable
private FileInfo doGetInfo(String path) {
FileInfo info = myCache.get(path);
if (info == null) {
info = myKernel.getInfo(path.replace('/', '\\'));
if (info == null) {
throw new FileNotFoundException(path);
return null;
}
myCache.put(path, info);
}
return info;
}
@NewVirtualFileSystem.FileBooleanAttributes
public int getBooleanAttributes(@NotNull String path, @NewVirtualFileSystem.FileBooleanAttributes int flags) {
FileInfo info = doGetInfo(path);
int result = 0;
if ((flags & NewVirtualFileSystem.BA_EXISTS) != 0) {
result |= info == null ? 0 : NewVirtualFileSystem.BA_EXISTS;
}
if ((flags & NewVirtualFileSystem.BA_DIRECTORY) != 0) {
result |= info == null || (info.attributes & FILE_ATTRIBUTE_DIRECTORY) == 0 ? 0 : NewVirtualFileSystem.BA_DIRECTORY;
}
if ((flags & NewVirtualFileSystem.BA_REGULAR) != 0) {
result |= info == null || (info.attributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_REPARSE_POINT)) != 0 ? 0 : NewVirtualFileSystem.BA_REGULAR;
}
if ((flags & NewVirtualFileSystem.BA_HIDDEN) != 0) {
result |= info == null || (info.attributes & FILE_ATTRIBUTE_HIDDEN) == 0 ? 0 : NewVirtualFileSystem.BA_HIDDEN;
}
return result;
}
}
@@ -33,33 +33,34 @@ import java.util.Set;
public class Win32LocalFileSystem extends LocalFileSystemBase {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.win32.Win32LocalFileSystem");
private static boolean ourIsAvailable;
private static final boolean ourIsAvailable;
static {
boolean available = false;
if (SystemInfo.isWindows) {
String libName = SystemInfo.is64Bit ? "IdeaWin64" : "IdeaWin32";
try {
System.load(PathManager.getHomePath() + "/community/bin/win/" + libName + ".dll");
ourIsAvailable = true;
available = true;
}
catch (Throwable t0) {
try {
System.load(PathManager.getHomePath() + "/bin/win/" + libName + ".dll");
ourIsAvailable = true;
available = true;
}
catch (Throwable t1) {
try {
System.loadLibrary(libName);
ourIsAvailable = true;
available = true;
}
catch (Throwable t2) {
LOG.warn("Failed to load native filesystem for Windows", t2);
ourIsAvailable = false;
}
}
}
}
if (ourIsAvailable) {
ourIsAvailable = available;
if (available) {
LOG.info("Native filesystem for Windows is operational");
}
}
@@ -108,16 +109,11 @@ public class Win32LocalFileSystem extends LocalFileSystemBase {
@Override
public boolean exists(@NotNull VirtualFile fileOrDirectory) {
if (fileOrDirectory.getParent() == null) return true;
try {
myKernel.exists(fileOrDirectory.getPath());
if (checkMe && !super.exists(fileOrDirectory)) {
LOG.error(fileOrDirectory.getPath());
}
return true;
}
catch (FileNotFoundException e) {
return super.exists(fileOrDirectory);
boolean b = myKernel.exists(fileOrDirectory.getPath());
if (checkMe && b != super.exists(fileOrDirectory)) {
LOG.error(fileOrDirectory.getPath());
}
return b;
}
@Override
@@ -196,4 +192,9 @@ public class Win32LocalFileSystem extends LocalFileSystemBase {
public void removeWatchedRoot(@NotNull WatchRequest watchRequest) {
throw new UnsupportedOperationException();
}
@Override
public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
return myKernel.getBooleanAttributes(file.getPath(), flags);
}
}
@@ -42,6 +42,7 @@ import com.intellij.openapi.vfs.newvfs.events.VFileCreateEvent;
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
import com.intellij.util.ArrayUtil;
import com.intellij.util.PathUtil;
import com.intellij.util.SmartList;
import com.intellij.util.SystemProperties;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.text.CaseInsensitiveStringHashingStrategy;
@@ -312,14 +313,15 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
return VfsUtil.toVirtualFileArray(roots);
}
@Nullable
private VirtualFileSystemEntry createAndFindChildWithEventFire(@NotNull String name) {
final NewVirtualFileSystem delegate = getFileSystem();
VirtualFile fake = new FakeVirtualFile(this, name);
if (delegate.exists(fake)) {
int attributes = delegate.getBooleanAttributes(fake, NewVirtualFileSystem.BA_EXISTS | NewVirtualFileSystem.BA_DIRECTORY);
if ((attributes & NewVirtualFileSystem.BA_EXISTS) != 0) {
final String realName = delegate.getCanonicallyCasedName(fake);
VFileCreateEvent event = new VFileCreateEvent(null, this, realName, delegate.isDirectory(fake), true);
boolean isDir = (attributes & NewVirtualFileSystem.BA_DIRECTORY) != 0;
VFileCreateEvent event = new VFileCreateEvent(null, this, realName, isDir, true);
RefreshQueue.getInstance().processSingleEvent(event);
return findChild(realName);
}
@@ -526,14 +528,16 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
final Map<String, VirtualFileSystemEntry> map = asMap();
if (map == null) return Collections.emptyList();
List<String> names = new ArrayList<String>();
List<String> names = null;
for (Map.Entry<String, VirtualFileSystemEntry> entry : map.entrySet()) {
if (entry.getValue() == NULL_VIRTUAL_FILE) {
if (names == null) names = new SmartList<String>();
names.add(entry.getKey());
}
}
return names;
return names == null ? Collections.<String>emptyList() : names;
}
@Override
@@ -48,6 +48,7 @@ import gnu.trove.TIntObjectHashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import java.io.*;
import java.util.*;
@@ -189,7 +190,8 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
childrenIds[i] = currentIds[idx];
}
else {
int childId = createAndCopyRecord(delegate, new FakeVirtualFile(file, name), id);
FakeVirtualFile child = new FakeVirtualFile(file, name);
int childId = createAndCopyRecord(delegate, child, id, delegate.isDirectory(child));
childrenIds[i] = childId;
}
}
@@ -283,12 +285,16 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
return FSRecords.getModCount();
}
private static boolean copyRecordFromDelegateFS(final int id, final int parentId, final VirtualFile file, NewVirtualFileSystem delegate) {
private static boolean copyRecordFromDelegateFS(final int id,
final int parentId,
final VirtualFile file,
NewVirtualFileSystem delegate,
boolean isDir) {
String name = file.getName();
if (name.length() > 0 && namesEqual(delegate, name, FSRecords.getName(id))) return false; // TODO: Handle root attributes change.
if (!name.isEmpty() && namesEqual(delegate, name, FSRecords.getName(id))) return false; // TODO: Handle root attributes change.
if (name.length() == 0) { // TODO: hack
if (name.isEmpty()) { // TODO: hack
if (areChildrenLoaded(id)) return false;
}
@@ -299,11 +305,9 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
FSRecords.setTimestamp(id, delegate.getTimeStamp(file));
boolean directory = delegate.isDirectory(file);
FSRecords.setLength(id, isDir ? -1L : delegate.getLength(file));
FSRecords.setLength(id, directory ? -1L : delegate.getLength(file));
FSRecords.setFlags(id, (directory ? IS_DIRECTORY_FLAG : 0) |
FSRecords.setFlags(id, (isDir ? IS_DIRECTORY_FLAG : 0) |
(delegate.isWritable(file) ? 0 : IS_READ_ONLY) |
(delegate.isSymLink(file) ? IS_SYMLINK : 0) |
(delegate.isSpecialFile(file) ? IS_SPECIAL : 0), true);
@@ -398,8 +402,10 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
}
VirtualFile fake = new FakeVirtualFile(parent, childName);
if (delegate.exists(fake)) {
int child = createAndCopyRecord(delegate, fake, parentId);
int attributes = delegate.getBooleanAttributes(fake, NewVirtualFileSystem.BA_EXISTS | NewVirtualFileSystem.BA_DIRECTORY);
if ((attributes & NewVirtualFileSystem.BA_EXISTS) != 0) {
boolean isDir = (attributes & NewVirtualFileSystem.BA_DIRECTORY) != 0;
int child = createAndCopyRecord(delegate, fake, parentId, isDir);
FSRecords.updateList(parentId, ArrayUtil.append(children, child));
return child;
}
@@ -722,13 +728,13 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
synchronized (LOCK) {
final String rootUrl = fs.getProtocol() + "://" + basePath;
VirtualFileSystemEntry root = myRoots.get(rootUrl);
if (root == null && basePath.length() == 0) {
if (root == null && basePath.isEmpty()) {
root = myFakeRoot;
}
if (root == null) {
try {
final int rootId = FSRecords.findRootRecord(rootUrl);
if (basePath.length() > 0) {
if (!basePath.isEmpty()) {
root = new VirtualDirectoryImpl(basePath, null, fs, rootId) {
@NotNull
@Override
@@ -756,14 +762,14 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
@Override
public VirtualFileSystemEntry findChild(@NotNull String name) {
if (name.length() == 0) return null;
if (name.isEmpty()) return null;
return findRoot(name, fs);
}
};
}
if (!fs.exists(root)) return null;
boolean newRoot = copyRecordFromDelegateFS(rootId, 0, root, fs);
boolean newRoot = copyRecordFromDelegateFS(rootId, 0, root, fs, true);
if (!newRoot) {
if (fs.getTimeStamp(root) != FSRecords.getTimestamp(rootId)) {
root.markDirtyRecursively();
@@ -774,7 +780,7 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
throw new RuntimeException(e);
}
if (basePath.length() > 0) {
if (!basePath.isEmpty()) {
myRoots.put(rootUrl, root);
myRootsById.put(root.getId(), root);
}
@@ -949,10 +955,12 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
private static void executeCreateChild(final VirtualFile parent, final String name) {
final NewVirtualFileSystem delegate = getDelegate(parent);
VirtualFile fakeFile = new FakeVirtualFile(parent, name);
if (delegate.exists(fakeFile)) {
VirtualFile fake = new FakeVirtualFile(parent, name);
int attributes = delegate.getBooleanAttributes(fake, NewVirtualFileSystem.BA_EXISTS | NewVirtualFileSystem.BA_DIRECTORY);
if ((attributes & NewVirtualFileSystem.BA_EXISTS) != 0) {
final int parentId = getFileId(parent);
int childId = createAndCopyRecord(delegate, fakeFile, parentId);
boolean isDir = (attributes & NewVirtualFileSystem.BA_DIRECTORY) != 0;
int childId = createAndCopyRecord(delegate, fake, parentId, isDir);
appendIdToParentList(parentId, childId);
final VirtualDirectoryImpl dir = (VirtualDirectoryImpl)parent;
@@ -960,9 +968,9 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
}
}
private static int createAndCopyRecord(NewVirtualFileSystem delegateSystem, VirtualFile delegateFile, int parentId) {
private static int createAndCopyRecord(NewVirtualFileSystem delegateSystem, VirtualFile delegateFile, int parentId, boolean isDir) {
int childId = FSRecords.createRecord();
copyRecordFromDelegateFS(childId, parentId, delegateFile, delegateSystem);
copyRecordFromDelegateFS(childId, parentId, delegateFile, delegateSystem, isDir);
return childId;
}
@@ -1067,7 +1075,7 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
FSRecords.setLength(getFileId(file), delegate.getLength(file));
FSRecords.setTimestamp(getFileId(file), delegate.getTimeStamp(file));
((NewVirtualFile)file).setModificationStamp(newModificationStamp);
((VirtualFileSystemEntry)file).setModificationStamp(newModificationStamp);
}
@SuppressWarnings({"UnusedDeclaration"})
@@ -1092,6 +1100,7 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
return FSRecords.getName(id);
}
@TestOnly
public void cleanPersistedContents() {
try {
final int[] roots = FSRecords.listRoots();
@@ -1104,6 +1113,7 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
}
}
@TestOnly
private static void cleanPersistedContentsRecursively(int id) {
if (isDirectory(id)) {
for (int child : FSRecords.list(id)) {
@@ -1116,11 +1126,12 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
}
public static NewVirtualFileSystem replaceWithNativeFS(NewVirtualFileSystem delegate) {
if (delegate.getProtocol().equals(LocalFileSystem.PROTOCOL) && Registry.is("filesystem.useNative")) {
if (SystemInfo.isWindows && Win32LocalFileSystem.isAvailable()) {
delegate = Win32LocalFileSystem.getWin32Instance();
}
}
if (delegate.getProtocol().equals(LocalFileSystem.PROTOCOL) &&
Registry.is("filesystem.useNative") &&
SystemInfo.isWindows &&
Win32LocalFileSystem.isAvailable()) {
delegate = Win32LocalFileSystem.getWin32Instance();
}
return delegate;
}
}
@@ -25,6 +25,7 @@ import com.intellij.openapi.vfs.newvfs.impl.FakeVirtualFile;
import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl;
import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry;
import com.intellij.util.containers.Queue;
import org.jetbrains.annotations.NotNull;
import java.util.*;
@@ -47,12 +48,15 @@ public class RefreshWorker {
public void scan() {
final NewVirtualFile root = (NewVirtualFile)myRefreshRoot;
NewVirtualFileSystem delegate = root.getFileSystem();
if (root.isDirty() && !delegate.exists(root)) {
int attributes = delegate.getBooleanAttributes(root, NewVirtualFileSystem.BA_EXISTS | NewVirtualFileSystem.BA_DIRECTORY);
if (root.isDirty() && (attributes & NewVirtualFileSystem.BA_EXISTS) == 0) {
scheduleDeletion(root);
root.markClean();
}
else {
if (root.isDirectory()) {
boolean isDir = (attributes & NewVirtualFileSystem.BA_DIRECTORY) != 0;
if (isDir) {
delegate = PersistentFS.replaceWithNativeFS(delegate);
}
@@ -86,14 +90,16 @@ public class RefreshWorker {
for (VirtualFile child : file.getChildren()) {
if (!deletedNames.contains(child.getName())) {
scheduleChildRefresh(file, child, delegate);
int childAttributes = delegate.getBooleanAttributes(child, -1);
scheduleChildRefresh(file, child, delegate, childAttributes);
}
}
}
else {
for (VirtualFile child : file.getCachedChildren()) {
if (delegate.exists(child)) {
scheduleChildRefresh(file, child, delegate);
int childAttributes = delegate.getBooleanAttributes(child, -1);
if ((childAttributes & NewVirtualFileSystem.BA_EXISTS) != 0) {
scheduleChildRefresh(file, child, delegate, childAttributes);
}
else {
scheduleDeletion(child);
@@ -102,11 +108,13 @@ public class RefreshWorker {
final List<String> names = dir.getSuspiciousNames();
for (String name : names) {
if (name.length() == 0) continue;
if (name.isEmpty()) continue;
final VirtualFile fake = new FakeVirtualFile(file, name);
if (delegate.exists(fake)) {
scheduleCreation(file, name, delegate.isDirectory(fake));
int attrs = delegate.getBooleanAttributes(fake, NewVirtualFileSystem.BA_EXISTS | NewVirtualFileSystem.BA_DIRECTORY);
if ((attrs & NewVirtualFileSystem.BA_EXISTS) != 0) {
boolean isDira = (attrs & NewVirtualFileSystem.BA_DIRECTORY) != 0;
scheduleCreation(file, name, isDira);
}
}
}
@@ -132,13 +140,16 @@ public class RefreshWorker {
}
}
private void scheduleChildRefresh(final VirtualFileSystemEntry file, final VirtualFile child, final NewVirtualFileSystem delegate) {
private void scheduleChildRefresh(@NotNull VirtualFileSystemEntry file,
@NotNull VirtualFile child,
@NotNull NewVirtualFileSystem delegate,
@NewVirtualFileSystem.FileBooleanAttributes int childAttributes) {
final boolean currentIsDirectory = child.isDirectory();
final boolean currentIsSymlink = child.isSymLink();
final boolean currentIsSpecial = child.isSpecialFile();
final boolean upToDateIsDirectory = delegate.isDirectory(child);
final boolean upToDateIsDirectory = (childAttributes & NewVirtualFileSystem.BA_DIRECTORY) != 0;
final boolean upToDateIsSymlink = delegate.isSymLink(child);
final boolean upToDateIsSpecial = delegate.isSpecialFile(child);
final boolean upToDateIsSpecial = (childAttributes & (NewVirtualFileSystem.BA_REGULAR | NewVirtualFileSystem.BA_DIRECTORY | NewVirtualFileSystem.BA_EXISTS)) == NewVirtualFileSystem.BA_EXISTS;
if (currentIsDirectory != upToDateIsDirectory || currentIsSymlink != upToDateIsSymlink || currentIsSpecial != upToDateIsSpecial) {
scheduleDeletion(child);
scheduleReCreation(file, child.getName(), upToDateIsDirectory);
@@ -251,4 +251,9 @@ public class MockLocalFileSystem extends LocalFileSystem {
public int getRank() {
return 1;
}
@Override
public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
return 0;
}
}
@@ -41,7 +41,7 @@ import java.util.regex.Pattern;
@SuppressWarnings({"UtilityClassWithoutPrivateConstructor"})
public class FileUtil {
public static final int MEGABYTE = 1024 * 1024;
public static final String ASYNC_DELETE_EXTENSION = ".__del__";
@NonNls public static final String ASYNC_DELETE_EXTENSION = ".__del__";
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.io.FileUtil");
@@ -681,7 +681,7 @@ public class FileUtil {
final int oldPermissions = FileSystemUtil.getPermissions(fromFile);
final int newPermissions = FileSystemUtil.getPermissions(toFile);
if (oldPermissions != -1 && newPermissions != -1) {
FileSystemUtil.setPermissions(toFile, (oldPermissions | newPermissions));
FileSystemUtil.setPermissions(toFile, oldPermissions | newPermissions);
}
}
}
@@ -713,7 +713,7 @@ public class FileUtil {
public static void copyDir(@NotNull File fromDir, @NotNull File toDir, boolean copySystemFiles) throws IOException {
copyDir(fromDir, toDir, copySystemFiles ? null : new FileFilter() {
public boolean accept(File file) {
return !file.getName().startsWith(".");
return !StringUtil.startsWithChar(file.getName(), '.');
}
});
}
@@ -939,7 +939,7 @@ public class FileUtil {
final StringBuilder builder = new StringBuilder(antPattern.length());
int asteriskCount = 0;
boolean recursive = true;
final int start = ignoreStartingSlash && (antPattern.startsWith("/") || antPattern.startsWith("\\")) ? 1 : 0;
final int start = ignoreStartingSlash && (StringUtil.startsWithChar(antPattern, '/') || StringUtil.startsWithChar(antPattern, '\\')) ? 1 : 0;
for (int idx = start; idx < antPattern.length(); idx++) {
final char ch = antPattern.charAt(idx);