mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Use bulk file attributes reading
This commit is contained in:
@@ -38,6 +38,9 @@ import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
public class JarHandlerBase {
|
||||
private static final long DEFAULT_LENGTH = 0L;
|
||||
private static final long DEFAULT_TIMESTAMP = -1L;
|
||||
|
||||
protected final TimedReference<JarFile> myJarFile = new TimedReference<JarFile>(null);
|
||||
protected SoftReference<Map<String, EntryInfo>> myRelPathsToEntries = new SoftReference<Map<String, EntryInfo>>(null);
|
||||
protected final Object lock = new Object();
|
||||
@@ -246,7 +249,7 @@ public class JarHandlerBase {
|
||||
public long getLength(@NotNull final VirtualFile file) {
|
||||
synchronized (lock) {
|
||||
final JarFile.JarEntry entry = convertToEntry(file);
|
||||
return entry != null ? entry.getSize() : 0;
|
||||
return entry != null ? entry.getSize() : DEFAULT_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,7 +285,7 @@ public class JarHandlerBase {
|
||||
if (file.getParent() == null) return getOriginalFile().lastModified(); // Optimization
|
||||
synchronized (lock) {
|
||||
final JarFile.JarEntry entry = convertToEntry(file);
|
||||
return entry != null ? entry.getTime() : -1L;
|
||||
return entry != null ? entry.getTime() : DEFAULT_TIMESTAMP;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,8 +310,12 @@ public class JarHandlerBase {
|
||||
@Nullable
|
||||
public FileAttributes getAttributes(@NotNull final VirtualFile file) {
|
||||
synchronized (lock) {
|
||||
final EntryInfo entryInfo = getEntryInfo(getRelativePath(file));
|
||||
if (entryInfo == null) return null;
|
||||
final JarFile.JarEntry entry = convertToEntry(file);
|
||||
return entry != null ? new FileAttributes(entry.isDirectory(), false, false, false, entry.getSize(), entry.getTime(), false) : null;
|
||||
final long length = entry != null ? entry.getSize() : DEFAULT_LENGTH;
|
||||
final long timeStamp = entry != null ? entry.getTime() : DEFAULT_TIMESTAMP;
|
||||
return new FileAttributes(entryInfo.isDirectory, false, false, false, length, timeStamp, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* Copyright 2000-2012 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.
|
||||
@@ -28,7 +28,11 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public interface FileSystemInterface {
|
||||
boolean exists(@NotNull VirtualFile fileOrDirectory);
|
||||
// default values for missing files (same as in corresponding java.io.File methods)
|
||||
long DEFAULT_LENGTH = 0;
|
||||
long DEFAULT_TIMESTAMP = 0;
|
||||
|
||||
boolean exists(@NotNull VirtualFile file);
|
||||
|
||||
@NotNull
|
||||
String[] list(@NotNull VirtualFile file);
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.intellij.openapi.vfs.newvfs;
|
||||
|
||||
import com.intellij.openapi.util.io.FileAttributes;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileListener;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
@@ -116,42 +115,6 @@ public abstract class NewVirtualFileSystem extends VirtualFileSystem implements
|
||||
return file.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 com.intellij.openapi.util.io.FileUtil#BA_EXISTS} is set if {@link java.io.File#exists()} returns true</li>
|
||||
* <li>{@link com.intellij.openapi.util.io.FileUtil#BA_DIRECTORY} is set if {@link java.io.File#isDirectory()} returns true</li>
|
||||
* <li>{@link com.intellij.openapi.util.io.FileUtil#BA_HIDDEN} is set if {@link java.io.File#isHidden()} returns true</li>
|
||||
* <li>{@link com.intellij.openapi.util.io.FileUtil#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>
|
||||
*/
|
||||
@FileUtil.FileBooleanAttributes
|
||||
public abstract int getBooleanAttributes(@NotNull final VirtualFile file, @FileUtil.FileBooleanAttributes int flags);
|
||||
|
||||
/**
|
||||
* Reads various file attributes in one shot (to reduce the number of native I/O calls).
|
||||
*
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.intellij.openapi.vfs.ex.temp;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.util.io.BufferExposingByteArrayInputStream;
|
||||
import com.intellij.openapi.util.io.FileAttributes;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.ManagingFS;
|
||||
@@ -368,15 +367,6 @@ public class TempFileSystem extends NewVirtualFileSystem {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
|
||||
FSItem item = convert(file);
|
||||
int isDir = item instanceof FSDir ? FileUtil.BA_DIRECTORY : 0;
|
||||
int exists = item == null ? 0 : FileUtil.BA_EXISTS;
|
||||
int regular = isDir == 0 ? FileUtil.BA_REGULAR : 0;
|
||||
return isDir | exists | regular;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileAttributes getAttributes(@NotNull final VirtualFile file) {
|
||||
final FSItem item = convert(file);
|
||||
|
||||
+1
-20
@@ -359,24 +359,6 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo
|
||||
return VfsImplUtil.refreshAndFindFileByPath(this, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
|
||||
int exists = 0;
|
||||
JarHandler handler = getHandler(file);
|
||||
if ((flags & FileUtil.BA_EXISTS) != 0) {
|
||||
exists = handler.exists(file) ? FileUtil.BA_EXISTS : 0;
|
||||
}
|
||||
int isDir = 0;
|
||||
if ((flags & FileUtil.BA_DIRECTORY) != 0) {
|
||||
isDir = handler.isDirectory(file) ? FileUtil.BA_DIRECTORY : 0;
|
||||
}
|
||||
int regular = 0;
|
||||
if ((flags & FileUtil.BA_REGULAR) != 0) {
|
||||
regular = isDir == 0 ? FileUtil.BA_REGULAR : 0;
|
||||
}
|
||||
return exists | isDir | regular;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileAttributes getAttributes(@NotNull final VirtualFile file) {
|
||||
final JarHandler handler = getHandler(file);
|
||||
@@ -385,8 +367,7 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo
|
||||
if (file.getParent() == null) {
|
||||
final LocalFileSystem localFileSystem = LocalFileSystem.getInstance();
|
||||
final VirtualFile originalFile = localFileSystem.findFileByIoFile(handler.getOriginalFile());
|
||||
assert originalFile != null : file;
|
||||
return localFileSystem.getAttributes(originalFile);
|
||||
return originalFile != null ? localFileSystem.getAttributes(originalFile) : null;
|
||||
}
|
||||
|
||||
return handler.getAttributes(file);
|
||||
|
||||
+33
-48
@@ -52,8 +52,8 @@ import java.util.Locale;
|
||||
public abstract class LocalFileSystemBase extends LocalFileSystem {
|
||||
protected static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl");
|
||||
|
||||
protected static final long DEFAULT_LENGTH = 0;
|
||||
protected static final long DEFAULT_TIMESTAMP = 0;
|
||||
private static final FileAttributes FAKE_ROOT_ATTRIBUTES =
|
||||
new FileAttributes(true, false, false, false, DEFAULT_LENGTH, DEFAULT_TIMESTAMP, false);
|
||||
|
||||
private final List<LocalFileOperationsHandler> myHandlers = new ArrayList<LocalFileOperationsHandler>();
|
||||
|
||||
@@ -143,14 +143,8 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
|
||||
private static File convertToIOFileAndCheck(@NotNull final VirtualFile file) throws FileNotFoundException {
|
||||
final File ioFile = convertToIOFile(file);
|
||||
|
||||
int intFlags = FileUtil.getBooleanAttributes(ioFile);
|
||||
if (intFlags != -1) {
|
||||
if ((intFlags & FileUtil.BA_EXISTS) != 0 && (intFlags & FileUtil.BA_REGULAR) == 0) {
|
||||
throw new FileNotFoundException("Not a file: " + ioFile);
|
||||
}
|
||||
return ioFile;
|
||||
}
|
||||
if (ioFile.exists() && !ioFile.isFile()) {
|
||||
final FileAttributes attributes = FileSystemUtil.getAttributes(ioFile);
|
||||
if (attributes != null && !attributes.isFile()) {
|
||||
throw new FileNotFoundException("Not a file: " + ioFile);
|
||||
}
|
||||
|
||||
@@ -158,36 +152,38 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(@NotNull final VirtualFile fileOrDirectory) {
|
||||
String path = fileOrDirectory.getPath();
|
||||
if (fileOrDirectory.getParent() == null && path.startsWith("//")) return true; // Windows UNC root like //unit-333
|
||||
if (StringUtil.isEmpty(path)) return true; // fake top dir for Windows
|
||||
return convertToIOFile(fileOrDirectory).exists();
|
||||
public boolean exists(@NotNull final VirtualFile file) {
|
||||
return getAttributes(file) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLength(@NotNull final VirtualFile file) {
|
||||
return convertToIOFile(file).length();
|
||||
final FileAttributes attributes = getAttributes(file);
|
||||
return attributes != null ? attributes.length : DEFAULT_LENGTH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTimeStamp(@NotNull final VirtualFile file) {
|
||||
return convertToIOFile(file).lastModified();
|
||||
final FileAttributes attributes = getAttributes(file);
|
||||
return attributes != null ? attributes.lastModified : DEFAULT_TIMESTAMP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirectory(@NotNull final VirtualFile file) {
|
||||
return convertToIOFile(file).isDirectory();
|
||||
final FileAttributes attributes = getAttributes(file);
|
||||
return attributes != null && attributes.isDirectory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWritable(@NotNull final VirtualFile file) {
|
||||
return convertToIOFile(file).canWrite();
|
||||
final FileAttributes attributes = getAttributes(file);
|
||||
return attributes != null && attributes.isWritable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSymLink(@NotNull final VirtualFile file) {
|
||||
return FileSystemUtil.isSymLink(file.getPath());
|
||||
final FileAttributes attributes = getAttributes(file);
|
||||
return attributes != null && attributes.isSymLink();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -197,17 +193,8 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
|
||||
|
||||
@Override
|
||||
public boolean isSpecialFile(@NotNull final VirtualFile file) {
|
||||
if (!SystemInfo.isUnix) return false;
|
||||
final File ioFile = convertToIOFile(file);
|
||||
return isSpecialFile(ioFile);
|
||||
}
|
||||
|
||||
private static boolean isSpecialFile(@NotNull File ioFile) {
|
||||
int flags = FileUtil.getBooleanAttributes(ioFile);
|
||||
if (flags != -1) {
|
||||
return (flags & (FileUtil.BA_REGULAR | FileUtil.BA_DIRECTORY | FileUtil.BA_EXISTS)) == (~FileUtil.BA_REGULAR & ~FileUtil.BA_DIRECTORY & FileUtil.BA_EXISTS);
|
||||
}
|
||||
return !ioFile.isFile() && !ioFile.isDirectory() && ioFile.exists();
|
||||
final FileAttributes attributes = getAttributes(file);
|
||||
return attributes != null && attributes.isSpecial();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -243,6 +230,7 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
|
||||
return names == null ? ArrayUtil.EMPTY_STRING_ARRAY : names;
|
||||
}
|
||||
|
||||
// todo[r.sh] drop the restriction in favor of VfsUtilCore.visitChildrenRecursively()
|
||||
protected static boolean isInvalidSymLink(@NotNull final VirtualFile file) {
|
||||
if (!file.isSymLink()) return false;
|
||||
final VirtualFile target = file.getCanonicalFile();
|
||||
@@ -301,7 +289,7 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
|
||||
}
|
||||
}
|
||||
|
||||
RefreshQueue.getInstance().refresh(async, recursive, onFinish, VfsUtil.toVirtualFileArray(filesToRefresh));
|
||||
RefreshQueue.getInstance().refresh(async, recursive, onFinish, VfsUtilCore.toVirtualFileArray(filesToRefresh));
|
||||
}
|
||||
finally {
|
||||
if (fireCommonRefreshSession) manager.fireAfterRefreshFinish(false);
|
||||
@@ -323,7 +311,7 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
|
||||
collection = new ArrayList<VirtualFile>();
|
||||
ContainerUtil.addAll(collection, files);
|
||||
}
|
||||
RefreshQueue.getInstance().refresh(async, recursive, onFinish, VfsUtil.toVirtualFileArray(collection));
|
||||
RefreshQueue.getInstance().refresh(async, recursive, onFinish, VfsUtilCore.toVirtualFileArray(collection));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -570,11 +558,13 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
|
||||
@NotNull final VirtualFile vFile,
|
||||
@NotNull final VirtualFile newParent,
|
||||
@NotNull final String copyName) throws IOException {
|
||||
File physicalFile = convertToIOFile(vFile);
|
||||
if (isSpecialFile(physicalFile)) {
|
||||
throw new FileNotFoundException("Not a file: " + physicalFile);
|
||||
final FileAttributes attributes = getAttributes(vFile);
|
||||
|
||||
if (attributes == null || attributes.isSpecial()) {
|
||||
throw new FileNotFoundException("Not a file: " + vFile);
|
||||
}
|
||||
|
||||
File physicalFile = convertToIOFile(vFile);
|
||||
File physicalCopy = auxCopy(vFile, newParent, copyName);
|
||||
|
||||
try {
|
||||
@@ -583,7 +573,7 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
|
||||
physicalCopy = new File(newPhysicalParent, copyName);
|
||||
|
||||
try {
|
||||
if (physicalFile.isDirectory()) {
|
||||
if (attributes.isDirectory()) {
|
||||
FileUtil.copyDir(physicalFile, physicalCopy);
|
||||
}
|
||||
else {
|
||||
@@ -604,6 +594,7 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return new FakeVirtualFile(newParent, copyName);
|
||||
}
|
||||
|
||||
@@ -725,19 +716,13 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
|
||||
int attributes = FileUtil.getBooleanAttributes(convertToIOFile(file));
|
||||
if (attributes != -1) return attributes & flags;
|
||||
return ((flags & FileUtil.BA_EXISTS) != 0 && exists(file) ? FileUtil.BA_EXISTS : 0) |
|
||||
((flags & FileUtil.BA_DIRECTORY) != 0 && isDirectory(file) ? FileUtil.BA_DIRECTORY : 0) |
|
||||
((flags & FileUtil.BA_REGULAR) != 0 && !isSpecialFile(file) ? FileUtil.BA_REGULAR : 0) |
|
||||
((flags & FileUtil.BA_HIDDEN) != 0 && convertToIOFile(file).isHidden() ? FileUtil.BA_HIDDEN : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileAttributes getAttributes(@NotNull final VirtualFile file) {
|
||||
return FileSystemUtil.getAttributes(FileUtil.toSystemDependentName(file.getPath()));
|
||||
final String path = file.getPath();
|
||||
if (StringUtil.isEmpty(path) || file.getParent() == null && path.startsWith("//")) {
|
||||
return FAKE_ROOT_ATTRIBUTES; // fake Windows roots
|
||||
}
|
||||
return FileSystemUtil.getAttributes(FileUtil.toSystemDependentName(path));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.openapi.vfs.impl.win32;
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.io.win32.FileInfo;
|
||||
import com.intellij.openapi.util.io.win32.IdeaWin32;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -81,26 +80,4 @@ class Win32FsCache {
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
@FileUtil.FileBooleanAttributes
|
||||
int getBooleanAttributes(@NotNull VirtualFile file, @FileUtil.FileBooleanAttributes int flags) {
|
||||
FileInfo info = getInfo(file);
|
||||
if (info == null) return 0;
|
||||
|
||||
int result = 0;
|
||||
if ((flags & FileUtil.BA_EXISTS) != 0) {
|
||||
result |= FileUtil.BA_EXISTS;
|
||||
}
|
||||
if ((flags & FileUtil.BA_DIRECTORY) != 0) {
|
||||
result |= (info.attributes & FileInfo.FILE_ATTRIBUTE_DIRECTORY) == 0 ? 0 : FileUtil.BA_DIRECTORY;
|
||||
}
|
||||
if ((flags & FileUtil.BA_REGULAR) != 0) {
|
||||
result |= (info.attributes & (FileInfo.FILE_ATTRIBUTE_DIRECTORY | FileInfo.FILE_ATTRIBUTE_DEVICE | FileInfo.FILE_ATTRIBUTE_REPARSE_POINT)) != 0
|
||||
? 0 : FileUtil.BA_REGULAR;
|
||||
}
|
||||
if ((flags & FileUtil.BA_HIDDEN) != 0) {
|
||||
result |= (info.attributes & FileInfo.FILE_ATTRIBUTE_HIDDEN) == 0 ? 0 : FileUtil.BA_HIDDEN;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
+15
-8
@@ -66,9 +66,9 @@ public class Win32LocalFileSystem extends LocalFileSystemBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(@NotNull VirtualFile fileOrDirectory) {
|
||||
if (fileOrDirectory.getParent() == null) return true;
|
||||
return myFsCache.getInfo(fileOrDirectory) != null;
|
||||
public boolean exists(@NotNull VirtualFile file) {
|
||||
if (file.getParent() == null) return true;
|
||||
return myFsCache.getInfo(file) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -83,6 +83,18 @@ public class Win32LocalFileSystem extends LocalFileSystemBase {
|
||||
return fileInfo != null && notSet(fileInfo.attributes, FileInfo.FILE_ATTRIBUTE_READONLY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSymLink(@NotNull VirtualFile file) {
|
||||
final FileInfo fileInfo = myFsCache.getInfo(file);
|
||||
return fileInfo != null && isSet(fileInfo.attributes, FileInfo.FILE_ATTRIBUTE_REPARSE_POINT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpecialFile(@NotNull VirtualFile file) {
|
||||
final FileInfo fileInfo = myFsCache.getInfo(file);
|
||||
return fileInfo != null && isSet(fileInfo.attributes, FileInfo.FILE_ATTRIBUTE_DEVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTimeStamp(@NotNull VirtualFile file) {
|
||||
final FileInfo fileInfo = myFsCache.getInfo(file);
|
||||
@@ -112,9 +124,4 @@ public class Win32LocalFileSystem extends LocalFileSystemBase {
|
||||
@Nullable Collection<String> flatRoots) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
|
||||
return myFsCache.getBooleanAttributes(file, flags);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -25,6 +25,7 @@ import com.intellij.openapi.roots.OrderEnumerator;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileAttributes;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
@@ -311,12 +312,11 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
|
||||
@Nullable
|
||||
private VirtualFileSystemEntry createAndFindChildWithEventFire(@NotNull String name) {
|
||||
final NewVirtualFileSystem delegate = getFileSystem();
|
||||
VirtualFile fake = new FakeVirtualFile(this, name);
|
||||
int attributes = delegate.getBooleanAttributes(fake, FileUtil.BA_EXISTS | FileUtil.BA_DIRECTORY);
|
||||
if ((attributes & FileUtil.BA_EXISTS) != 0) {
|
||||
final VirtualFile fake = new FakeVirtualFile(this, name);
|
||||
final FileAttributes attributes = delegate.getAttributes(fake);
|
||||
if (attributes != null) {
|
||||
final String realName = delegate.getCanonicallyCasedName(fake);
|
||||
boolean isDir = (attributes & FileUtil.BA_DIRECTORY) != 0;
|
||||
VFileCreateEvent event = new VFileCreateEvent(null, this, realName, isDir, true);
|
||||
final VFileCreateEvent event = new VFileCreateEvent(null, this, realName, attributes.isDirectory(), true);
|
||||
RefreshQueue.getInstance().processSingleEvent(event);
|
||||
return findChild(realName);
|
||||
}
|
||||
|
||||
+3
-3
@@ -19,7 +19,6 @@ import com.intellij.ide.ui.UISettings;
|
||||
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.ThrowableComputable;
|
||||
import com.intellij.openapi.util.io.FileSystemUtil;
|
||||
import com.intellij.openapi.util.io.FileTooBigException;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
@@ -87,8 +86,9 @@ public abstract class VirtualFileSystemEntry extends NewVirtualFile {
|
||||
}
|
||||
|
||||
private void calcLinkStatus() {
|
||||
putUserData(SYMLINK_TARGET, isSymLink() ? FileSystemUtil.resolveSymLink(getPath()) : null);
|
||||
setFlagInt(HAS_SYMLINK_FLAG, isSymLink() || ((VirtualFileSystemEntry)myParent).getFlagInt(HAS_SYMLINK_FLAG));
|
||||
boolean symLink = isSymLink();
|
||||
putUserData(SYMLINK_TARGET, symLink ? myParent.getFileSystem().resolveSymLink(this) : null);
|
||||
setFlagInt(HAS_SYMLINK_FLAG, symLink || ((VirtualFileSystemEntry)myParent).getFlagInt(HAS_SYMLINK_FLAG));
|
||||
}
|
||||
|
||||
private static Object encodeName(@NotNull String name) {
|
||||
|
||||
+40
-42
@@ -23,10 +23,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.ShutDownTracker;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.BufferExposingByteArrayInputStream;
|
||||
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
|
||||
import com.intellij.openapi.util.io.ByteSequence;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.io.*;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.impl.win32.Win32LocalFileSystem;
|
||||
@@ -189,9 +186,10 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
|
||||
childrenIds[i] = currentIds[idx];
|
||||
}
|
||||
else {
|
||||
FakeVirtualFile child = new FakeVirtualFile(file, name);
|
||||
int attributes = delegate.getBooleanAttributes(child, -1);
|
||||
int childId = createAndCopyRecord(delegate, child, id, attributes);
|
||||
final FakeVirtualFile child = new FakeVirtualFile(file, name);
|
||||
final FileAttributes attributes = delegate.getAttributes(child);
|
||||
assert attributes != null : delegate + ": " + child;
|
||||
final int childId = createAndCopyRecord(delegate, child, id, attributes);
|
||||
childrenIds[i] = childId;
|
||||
}
|
||||
}
|
||||
@@ -289,32 +287,26 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
|
||||
private static boolean copyRecordFromDelegateFS(final int id,
|
||||
final int parentId,
|
||||
@NotNull VirtualFile file,
|
||||
@NotNull NewVirtualFileSystem delegate,
|
||||
@FileUtil.FileBooleanAttributes int attributes) {
|
||||
@NotNull NewVirtualFileSystem fs,
|
||||
@NotNull FileAttributes attributes) {
|
||||
String name = file.getName();
|
||||
|
||||
if (!name.isEmpty() && namesEqual(delegate, name, FSRecords.getName(id))) return false; // TODO: Handle root attributes change.
|
||||
|
||||
if (name.isEmpty()) { // TODO: hack
|
||||
if (areChildrenLoaded(id)) return false;
|
||||
if (!name.isEmpty()) {
|
||||
if (namesEqual(fs, name, FSRecords.getName(id))) return false; // TODO: Handle root attributes change.
|
||||
}
|
||||
else {
|
||||
if (areChildrenLoaded(id)) return false; // TODO: hack
|
||||
}
|
||||
|
||||
FSRecords.setParent(id, parentId);
|
||||
FSRecords.setName(id, name);
|
||||
|
||||
delegate = replaceWithNativeFS(delegate);
|
||||
FSRecords.setTimestamp(id, attributes.lastModified);
|
||||
FSRecords.setLength(id, attributes.isDirectory() ? -1L : attributes.length);
|
||||
|
||||
FSRecords.setTimestamp(id, delegate.getTimeStamp(file));
|
||||
|
||||
boolean isDir = (attributes & FileUtil.BA_DIRECTORY) != 0;
|
||||
FSRecords.setLength(id, isDir ? -1L : delegate.getLength(file));
|
||||
|
||||
boolean isSpecial = (attributes & (FileUtil.BA_REGULAR | FileUtil.BA_DIRECTORY | FileUtil.BA_EXISTS)) ==
|
||||
FileUtil.BA_EXISTS;
|
||||
FSRecords.setFlags(id, (isDir ? IS_DIRECTORY_FLAG : 0) |
|
||||
(delegate.isWritable(file) ? 0 : IS_READ_ONLY) |
|
||||
(delegate.isSymLink(file) ? IS_SYMLINK : 0) |
|
||||
(isSpecial ? IS_SPECIAL : 0), true);
|
||||
FSRecords.setFlags(id, (attributes.isDirectory() ? IS_DIRECTORY_FLAG : 0) |
|
||||
(attributes.isWritable() ? 0 : IS_READ_ONLY) |
|
||||
(attributes.isSymLink() ? IS_SYMLINK : 0) |
|
||||
(attributes.isSpecial() ? IS_SPECIAL : 0), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -404,10 +396,10 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
|
||||
if (namesEqual(delegate, childName, FSRecords.getName(childId))) return childId;
|
||||
}
|
||||
|
||||
VirtualFile fake = new FakeVirtualFile(parent, childName);
|
||||
int attributes = delegate.getBooleanAttributes(fake, -1);
|
||||
if ((attributes & FileUtil.BA_EXISTS) != 0) {
|
||||
int child = createAndCopyRecord(delegate, fake, parentId, attributes);
|
||||
final VirtualFile fake = new FakeVirtualFile(parent, childName);
|
||||
final FileAttributes attributes = delegate.getAttributes(fake);
|
||||
if (attributes != null) {
|
||||
final int child = createAndCopyRecord(delegate, fake, parentId, attributes);
|
||||
FSRecords.updateList(parentId, ArrayUtil.append(children, child));
|
||||
return child;
|
||||
}
|
||||
@@ -764,6 +756,7 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
|
||||
if (basePath.isEmpty()) {
|
||||
// fake root for windows
|
||||
root = new VirtualDirectoryImpl("", null, fs, rootId) {
|
||||
@SuppressWarnings("NonSynchronizedMethodOverridesSynchronizedMethod")
|
||||
@Override
|
||||
@NotNull
|
||||
public VirtualFile[] getChildren() {
|
||||
@@ -789,14 +782,15 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
|
||||
root = new VirtualDirectoryImpl(basePath, null, fs, rootId);
|
||||
}
|
||||
}
|
||||
if (!fs.exists(root)) {
|
||||
|
||||
final FileAttributes attributes = fs.getAttributes(root);
|
||||
if (attributes == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int attributes = FileUtil.BA_DIRECTORY | FileUtil.BA_EXISTS;
|
||||
boolean newRoot = copyRecordFromDelegateFS(rootId, 0, root, fs, attributes);
|
||||
final boolean newRoot = copyRecordFromDelegateFS(rootId, 0, root, fs, attributes);
|
||||
if (!newRoot) {
|
||||
if (fs.getTimeStamp(root) != FSRecords.getTimestamp(rootId)) {
|
||||
if (attributes.lastModified != FSRecords.getTimestamp(rootId)) {
|
||||
root.markDirtyRecursively();
|
||||
}
|
||||
}
|
||||
@@ -981,11 +975,11 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
|
||||
|
||||
private static void executeCreateChild(@NotNull VirtualFile parent, @NotNull String name) {
|
||||
final NewVirtualFileSystem delegate = getDelegate(parent);
|
||||
VirtualFile fake = new FakeVirtualFile(parent, name);
|
||||
int attributes = delegate.getBooleanAttributes(fake, -1);
|
||||
if ((attributes & FileUtil.BA_EXISTS) != 0) {
|
||||
final VirtualFile fake = new FakeVirtualFile(parent, name);
|
||||
final FileAttributes attributes = delegate.getAttributes(fake);
|
||||
if (attributes != null) {
|
||||
final int parentId = getFileId(parent);
|
||||
int childId = createAndCopyRecord(delegate, fake, parentId, attributes);
|
||||
final int childId = createAndCopyRecord(delegate, fake, parentId, attributes);
|
||||
appendIdToParentList(parentId, childId);
|
||||
assert parent instanceof VirtualDirectoryImpl : parent;
|
||||
final VirtualDirectoryImpl dir = (VirtualDirectoryImpl)parent;
|
||||
@@ -993,8 +987,11 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
|
||||
}
|
||||
}
|
||||
|
||||
private static int createAndCopyRecord(@NotNull NewVirtualFileSystem delegateSystem, @NotNull VirtualFile delegateFile, int parentId, @FileUtil.FileBooleanAttributes int attributes) {
|
||||
int childId = FSRecords.createRecord();
|
||||
private static int createAndCopyRecord(@NotNull NewVirtualFileSystem delegateSystem,
|
||||
@NotNull VirtualFile delegateFile,
|
||||
int parentId,
|
||||
@NotNull FileAttributes attributes) {
|
||||
final int childId = FSRecords.createRecord();
|
||||
copyRecordFromDelegateFS(childId, parentId, delegateFile, delegateSystem, attributes);
|
||||
return childId;
|
||||
}
|
||||
@@ -1097,8 +1094,9 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
|
||||
}
|
||||
|
||||
final NewVirtualFileSystem delegate = getDelegate(file);
|
||||
FSRecords.setLength(getFileId(file), delegate.getLength(file));
|
||||
FSRecords.setTimestamp(getFileId(file), delegate.getTimeStamp(file));
|
||||
final FileAttributes attributes = delegate.getAttributes(file);
|
||||
FSRecords.setLength(getFileId(file), attributes != null ? attributes.length : DEFAULT_LENGTH);
|
||||
FSRecords.setTimestamp(getFileId(file), attributes != null ? attributes.lastModified : DEFAULT_TIMESTAMP);
|
||||
|
||||
((VirtualFileSystemEntry)file).setModificationStamp(newModificationStamp);
|
||||
}
|
||||
|
||||
+92
-96
@@ -16,8 +16,7 @@
|
||||
package com.intellij.openapi.vfs.newvfs.persistent;
|
||||
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.io.FileAttributes;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.ManagingFS;
|
||||
@@ -36,152 +35,149 @@ import java.util.*;
|
||||
* @author max
|
||||
*/
|
||||
public class RefreshWorker {
|
||||
private final VirtualFile myRefreshRoot;
|
||||
private final boolean myIsRecursive;
|
||||
private final Queue<VirtualFile> myRefreshQueue = new Queue<VirtualFile>(100);
|
||||
|
||||
private final List<VFileEvent> myEvents = new ArrayList<VFileEvent>();
|
||||
|
||||
public RefreshWorker(final VirtualFile refreshRoot, final boolean isRecursive) {
|
||||
myRefreshRoot = refreshRoot;
|
||||
myIsRecursive = isRecursive;
|
||||
myRefreshQueue.addLast(refreshRoot);
|
||||
}
|
||||
|
||||
public void scan() {
|
||||
final NewVirtualFile root = (NewVirtualFile)myRefreshRoot;
|
||||
NewVirtualFileSystem delegate = root.getFileSystem();
|
||||
final int rootAttributes = delegate.getBooleanAttributes(root, -1);
|
||||
final NewVirtualFile root = (NewVirtualFile)myRefreshQueue.peekFirst();
|
||||
if (!root.isDirty()) return;
|
||||
|
||||
if (root.isDirty() && (rootAttributes & FileUtil.BA_EXISTS) == 0) {
|
||||
NewVirtualFileSystem fs = root.getFileSystem();
|
||||
final FileAttributes rootAttributes = fs.getAttributes(root);
|
||||
|
||||
if (rootAttributes == null) {
|
||||
scheduleDeletion(root);
|
||||
root.markClean();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if ((rootAttributes & FileUtil.BA_DIRECTORY) != 0) {
|
||||
delegate = PersistentFS.replaceWithNativeFS(delegate);
|
||||
|
||||
if (rootAttributes != null && rootAttributes.isDirectory()) {
|
||||
fs = PersistentFS.replaceWithNativeFS(fs);
|
||||
}
|
||||
|
||||
final PersistentFS persistence = (PersistentFS)ManagingFS.getInstance();
|
||||
|
||||
while (!myRefreshQueue.isEmpty()) {
|
||||
final VirtualFileSystemEntry file = (VirtualFileSystemEntry)myRefreshQueue.pullFirst();
|
||||
if (!file.isDirty()) continue;
|
||||
|
||||
final FileAttributes attributes = Comparing.equal(file, root) ? rootAttributes : fs.getAttributes(file);
|
||||
if (attributes == null) {
|
||||
scheduleDeletion(file);
|
||||
continue;
|
||||
}
|
||||
|
||||
final PersistentFS persistence = (PersistentFS)ManagingFS.getInstance();
|
||||
boolean checkFurther = true;
|
||||
final VirtualFileSystemEntry parent = file.getParent();
|
||||
if (parent != null && checkAndScheduleAttributesChange(parent, file, attributes)) {
|
||||
// ignore everything else
|
||||
checkFurther = false;
|
||||
}
|
||||
else if (file.isDirectory()) {
|
||||
final VirtualDirectoryImpl dir = (VirtualDirectoryImpl)file;
|
||||
final boolean fullSync = dir.allChildrenLoaded();
|
||||
if (fullSync) {
|
||||
final Set<String> currentNames = new HashSet<String>(Arrays.asList(persistence.list(file)));
|
||||
final Set<String> upToDateNames = new HashSet<String>(Arrays.asList(VfsUtil.filterNames(fs.list(file))));
|
||||
|
||||
while (!myRefreshQueue.isEmpty()) {
|
||||
final VirtualFileSystemEntry file = (VirtualFileSystemEntry)myRefreshQueue.pullFirst();
|
||||
if (!file.isDirty()) continue;
|
||||
final Set<String> newNames = new HashSet<String>(upToDateNames);
|
||||
newNames.removeAll(currentNames);
|
||||
|
||||
int attributes = Comparing.equal(file, root) ? rootAttributes : delegate.getBooleanAttributes(file, -1);
|
||||
VirtualFileSystemEntry parent = file.getParent();
|
||||
if (parent != null && checkAndScheduleAttributesChange(parent, file, delegate, attributes)) {
|
||||
// ignore everything else
|
||||
}
|
||||
else if (file.isDirectory()) {
|
||||
final VirtualDirectoryImpl dir = (VirtualDirectoryImpl)file;
|
||||
final boolean fullSync = dir.allChildrenLoaded();
|
||||
if (fullSync) {
|
||||
final Set<String> currentNames = new HashSet<String>(Arrays.asList(persistence.list(file)));
|
||||
final Set<String> upToDateNames = new HashSet<String>(Arrays.asList(VfsUtil.filterNames(delegate.list(file))));
|
||||
final Set<String> deletedNames = new HashSet<String>(currentNames);
|
||||
deletedNames.removeAll(upToDateNames);
|
||||
|
||||
final Set<String> newNames = new HashSet<String>(upToDateNames);
|
||||
newNames.removeAll(currentNames);
|
||||
|
||||
final Set<String> deletedNames = new HashSet<String>(currentNames);
|
||||
deletedNames.removeAll(upToDateNames);
|
||||
|
||||
for (String name : deletedNames) {
|
||||
scheduleDeletion(file.findChild(name));
|
||||
}
|
||||
|
||||
for (String name : newNames) {
|
||||
boolean isDirectory = delegate.isDirectory(new FakeVirtualFile(file, name));
|
||||
scheduleCreation(file, name, isDirectory);
|
||||
}
|
||||
|
||||
for (VirtualFile child : file.getChildren()) {
|
||||
if (!deletedNames.contains(child.getName())) {
|
||||
final int childAttributes = delegate.getBooleanAttributes(child, -1);
|
||||
scheduleChildRefresh(file, child, delegate, childAttributes);
|
||||
}
|
||||
}
|
||||
for (String name : deletedNames) {
|
||||
scheduleDeletion(file.findChild(name));
|
||||
}
|
||||
else {
|
||||
for (VirtualFile child : file.getCachedChildren()) {
|
||||
final int childAttributes = delegate.getBooleanAttributes(child, -1);
|
||||
if ((childAttributes & FileUtil.BA_EXISTS) != 0) {
|
||||
scheduleChildRefresh(file, child, delegate, childAttributes);
|
||||
}
|
||||
else {
|
||||
scheduleDeletion(child);
|
||||
}
|
||||
}
|
||||
|
||||
final List<String> names = dir.getSuspiciousNames();
|
||||
for (String name : names) {
|
||||
if (name.isEmpty()) continue;
|
||||
for (String name : newNames) {
|
||||
boolean isDirectory = fs.isDirectory(new FakeVirtualFile(file, name));
|
||||
scheduleCreation(file, name, isDirectory);
|
||||
}
|
||||
|
||||
final VirtualFile fake = new FakeVirtualFile(file, name);
|
||||
final int childAttributes = delegate.getBooleanAttributes(fake, FileUtil.BA_EXISTS | FileUtil.BA_DIRECTORY);
|
||||
if ((childAttributes & FileUtil.BA_EXISTS) != 0) {
|
||||
final boolean isDir = (childAttributes & FileUtil.BA_DIRECTORY) != 0;
|
||||
scheduleCreation(file, name, isDir);
|
||||
}
|
||||
for (VirtualFile child : file.getChildren()) {
|
||||
if (!deletedNames.contains(child.getName())) {
|
||||
checkAndScheduleChildRefresh(file, child, fs.getAttributes(child));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
long currentTimestamp = persistence.getTimeStamp(file);
|
||||
long upToDateTimestamp = delegate.getTimeStamp(file);
|
||||
long currentLength = SystemInfo.isUnix ? persistence.getLengthNoFollow(file) : -1;
|
||||
long upToDateLength = SystemInfo.isUnix ? delegate.getLength(file) : -1;
|
||||
for (VirtualFile child : file.getCachedChildren()) {
|
||||
final FileAttributes childAttributes = fs.getAttributes(child);
|
||||
if (childAttributes != null) {
|
||||
checkAndScheduleChildRefresh(file, child, childAttributes);
|
||||
}
|
||||
else {
|
||||
scheduleDeletion(child);
|
||||
}
|
||||
}
|
||||
|
||||
if (currentTimestamp != upToDateTimestamp || currentLength != upToDateLength) {
|
||||
scheduleUpdateContent(file);
|
||||
final List<String> names = dir.getSuspiciousNames();
|
||||
for (String name : names) {
|
||||
if (name.isEmpty()) continue;
|
||||
|
||||
final VirtualFile fake = new FakeVirtualFile(file, name);
|
||||
final FileAttributes childAttributes = fs.getAttributes(fake);
|
||||
if (childAttributes != null) {
|
||||
scheduleCreation(file, name, childAttributes.isDirectory());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
final long currentTimestamp = persistence.getTimeStamp(file);
|
||||
final long upToDateTimestamp = attributes.lastModified;
|
||||
final long currentLength = persistence.getLengthNoFollow(file);
|
||||
final long upToDateLength = attributes.length;
|
||||
|
||||
boolean currentWritable = persistence.isWritable(file);
|
||||
boolean upToDateWritable = delegate.isWritable(file);
|
||||
if (currentTimestamp != upToDateTimestamp || currentLength != upToDateLength) {
|
||||
scheduleUpdateContent(file);
|
||||
}
|
||||
}
|
||||
|
||||
if (checkFurther) {
|
||||
final boolean currentWritable = persistence.isWritable(file);
|
||||
final boolean upToDateWritable = attributes.isWritable();
|
||||
|
||||
if (currentWritable != upToDateWritable) {
|
||||
scheduleWritableAttributeChange(file, currentWritable, upToDateWritable);
|
||||
}
|
||||
|
||||
file.markClean();
|
||||
}
|
||||
|
||||
file.markClean();
|
||||
}
|
||||
}
|
||||
|
||||
private static final int SPECIAL_MASK = FileUtil.BA_REGULAR | FileUtil.BA_DIRECTORY | FileUtil.BA_EXISTS;
|
||||
|
||||
// todo[r.sh] compare link targets for files too
|
||||
private void scheduleChildRefresh(@NotNull VirtualFileSystemEntry parent,
|
||||
@NotNull VirtualFile child,
|
||||
@NotNull NewVirtualFileSystem delegate,
|
||||
@FileUtil.FileBooleanAttributes int childAttributes) {
|
||||
if (!checkAndScheduleAttributesChange(parent, child, delegate, childAttributes)) {
|
||||
boolean upToDateIsDirectory = (childAttributes & FileUtil.BA_DIRECTORY) != 0;
|
||||
private void checkAndScheduleChildRefresh(@NotNull VirtualFileSystemEntry parent,
|
||||
@NotNull VirtualFile child,
|
||||
@NotNull FileAttributes childAttributes) {
|
||||
if (!checkAndScheduleAttributesChange(parent, child, childAttributes)) {
|
||||
final boolean upToDateIsDirectory = childAttributes.isDirectory();
|
||||
if (myIsRecursive || !upToDateIsDirectory) {
|
||||
myRefreshQueue.addLast(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// returns true if change was detected and events scheduled
|
||||
private boolean checkAndScheduleAttributesChange(@NotNull VirtualFileSystemEntry parent,
|
||||
@NotNull VirtualFile child,
|
||||
@NotNull NewVirtualFileSystem delegate,
|
||||
@FileUtil.FileBooleanAttributes int childAttributes) {
|
||||
@NotNull FileAttributes childAttributes) {
|
||||
final boolean currentIsDirectory = child.isDirectory();
|
||||
final boolean currentIsSymlink = child.isSymLink();
|
||||
final boolean currentIsSpecial = child.isSpecialFile();
|
||||
//final String currentLinkTarget = child instanceof SymlinkDirectory ? ((SymlinkDirectory)child).getTargetPath() : null;
|
||||
final boolean upToDateIsDirectory = (childAttributes & FileUtil.BA_DIRECTORY) != 0;
|
||||
final boolean upToDateIsSymlink = delegate.isSymLink(child);
|
||||
final boolean upToDateIsSpecial = (childAttributes & SPECIAL_MASK) == FileUtil.BA_EXISTS;
|
||||
//final String upToDateLinkTarget = currentLinkTarget != null ? delegate.resolveSymLink(child) : null;
|
||||
final boolean upToDateIsDirectory = childAttributes.isDirectory();
|
||||
final boolean upToDateIsSymlink = childAttributes.isSymLink();
|
||||
final boolean upToDateIsSpecial = child.isSpecialFile();
|
||||
|
||||
if (currentIsDirectory != upToDateIsDirectory ||
|
||||
currentIsSymlink != upToDateIsSymlink ||
|
||||
currentIsSpecial != upToDateIsSpecial /*||
|
||||
!Comparing.equal(currentLinkTarget, upToDateLinkTarget)*/) {
|
||||
currentIsSpecial != upToDateIsSpecial) {
|
||||
scheduleDeletion(child);
|
||||
scheduleReCreation(parent, child.getName(), upToDateIsDirectory);
|
||||
return true;
|
||||
|
||||
+19
-4
@@ -29,6 +29,7 @@ import com.intellij.openapi.vfs.newvfs.NewVirtualFileSystem;
|
||||
import com.intellij.openapi.vfs.newvfs.RefreshQueue;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileDeleteEvent;
|
||||
import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl;
|
||||
import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry;
|
||||
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
|
||||
import com.intellij.testFramework.PlatformLangTestCase;
|
||||
import com.intellij.testFramework.PlatformTestUtil;
|
||||
@@ -245,10 +246,7 @@ public class LocalFileSystemTest extends PlatformLangTestCase {
|
||||
assertNotNull(virtualFile);
|
||||
|
||||
NewVirtualFileSystem fs = (NewVirtualFileSystem)virtualFile.getFileSystem();
|
||||
fs = PersistentFS.replaceWithNativeFS(fs);
|
||||
|
||||
assertTrue(fs.exists(virtualFile));
|
||||
final FileAttributes attributes = fs.getAttributes(virtualFile);
|
||||
FileAttributes attributes = fs.getAttributes(virtualFile);
|
||||
assertNotNull(attributes);
|
||||
assertEquals(FileAttributes.Type.FILE, attributes.type);
|
||||
assertEquals(FileAttributes.HIDDEN, attributes.flags);
|
||||
@@ -285,4 +283,21 @@ public class LocalFileSystemTest extends PlatformLangTestCase {
|
||||
}
|
||||
assertEquals(expectedCount, children.length);
|
||||
}
|
||||
|
||||
public void testSingleFileRootRefresh() throws Exception {
|
||||
File file = FileUtil.createTempFile("test.", ".txt");
|
||||
VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
|
||||
assertNotNull(virtualFile);
|
||||
assertTrue(virtualFile.exists());
|
||||
assertTrue(virtualFile.isValid());
|
||||
|
||||
virtualFile.refresh(false, false);
|
||||
assertFalse(((VirtualFileSystemEntry)virtualFile).isDirty());
|
||||
|
||||
FileUtil.delete(file);
|
||||
assertFalse(file.exists());
|
||||
virtualFile.refresh(false, false);
|
||||
assertFalse(virtualFile.exists());
|
||||
assertFalse(virtualFile.isValid());
|
||||
}
|
||||
}
|
||||
|
||||
+22
-3
@@ -54,21 +54,33 @@ public class SymlinkHandlingTest extends LightPlatformLangTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testBadLinksAreIgnored() throws Exception {
|
||||
public void testBadLinks() throws Exception {
|
||||
final File missingFile = new File(FileUtil.getTempDirectory(), "missing_file");
|
||||
assertTrue(missingFile.getAbsolutePath(), !missingFile.exists() || missingFile.delete());
|
||||
final File missingLinkFile = createTempLink(missingFile.getAbsolutePath(), "missing_link");
|
||||
final VirtualFile missingLinkVFile = refreshAndFind(missingLinkFile);
|
||||
assertNull(missingLinkVFile);
|
||||
assertBrokenLink(missingLinkVFile);
|
||||
|
||||
final File selfLinkFile = createTempLink("self_link", "self_link");
|
||||
final VirtualFile selfLinkVFile = refreshAndFind(selfLinkFile);
|
||||
assertNull(selfLinkVFile);
|
||||
assertBrokenLink(selfLinkVFile);
|
||||
|
||||
final File pointLinkFile = createTempLink(".", "point_link");
|
||||
final VirtualFile pointLinkVFile = refreshAndFind(pointLinkFile);
|
||||
assertNotNull(pointLinkVFile);
|
||||
assertTrue(pointLinkVFile.isSymLink());
|
||||
assertTrue(pointLinkVFile.isDirectory());
|
||||
assertEquals(0, pointLinkVFile.getChildren().length);
|
||||
System.out.println(pointLinkVFile.getCanonicalPath());
|
||||
|
||||
final File upLinkDir = FileUtil.createTempDirectory("dir1.", null);
|
||||
final File upLinkFile = createTempLink(upLinkDir.getAbsolutePath(), new File(upLinkDir, "up_link").getAbsolutePath());
|
||||
final VirtualFile upLinkVFile = refreshAndFind(upLinkFile);
|
||||
assertNotNull(upLinkVFile);
|
||||
assertTrue(upLinkVFile.isSymLink());
|
||||
assertTrue(upLinkVFile.isDirectory());
|
||||
assertEquals(0, upLinkVFile.getChildren().length);
|
||||
System.out.println(upLinkVFile.getCanonicalPath());
|
||||
|
||||
final File circularDir1 = FileUtil.createTempDirectory("dir1.", null);
|
||||
final File circularDir2 = FileUtil.createTempDirectory("dir2.", null);
|
||||
@@ -84,6 +96,13 @@ public class SymlinkHandlingTest extends LightPlatformLangTestCase {
|
||||
assertEquals(0, circularLink2VFile.getChildren()[0].getChildren().length);
|
||||
}
|
||||
|
||||
private static void assertBrokenLink(@Nullable VirtualFile link) {
|
||||
assertNotNull(link);
|
||||
assertTrue(link.isSymLink());
|
||||
assertEquals(0, link.getLength());
|
||||
assertNull(link.getCanonicalPath(), link.getCanonicalPath());
|
||||
}
|
||||
|
||||
public void testTargetIsWritable() throws Exception {
|
||||
final File targetFile = FileUtil.createTempFile("target", "");
|
||||
final File linkFile = createTempLink(targetFile.getAbsolutePath(), "link");
|
||||
|
||||
@@ -241,11 +241,6 @@ public class MockLocalFileSystem extends LocalFileSystem {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileAttributes getAttributes(@NotNull VirtualFile file) {
|
||||
return null;
|
||||
|
||||
@@ -123,6 +123,18 @@ public final class FileAttributes {
|
||||
return flags;
|
||||
}
|
||||
|
||||
public boolean isFile() {
|
||||
return type == Type.FILE;
|
||||
}
|
||||
|
||||
public boolean isDirectory() {
|
||||
return type == Type.DIRECTORY;
|
||||
}
|
||||
|
||||
public boolean isSpecial() {
|
||||
return type == Type.SPECIAL;
|
||||
}
|
||||
|
||||
public boolean isSymLink() {
|
||||
return isSet(flags, SYM_LINK);
|
||||
}
|
||||
|
||||
@@ -411,7 +411,7 @@ public class FileSystemUtil {
|
||||
|
||||
private JnaUnixMediatorImpl() throws Exception {
|
||||
myLibC = (LibC)Native.loadLibrary("c", LibC.class);
|
||||
mySharedMem = new Memory(512);
|
||||
mySharedMem = new Memory(256);
|
||||
myModeOffset = SystemInfo.isLinux ? (SystemInfo.is32Bit ? 16 : 24) :
|
||||
SystemInfo.isMac | SystemInfo.isFreeBSD ? 8 :
|
||||
SystemInfo.isSolaris ? (SystemInfo.is32Bit ? 20 : 16) :
|
||||
@@ -436,7 +436,6 @@ public class FileSystemUtil {
|
||||
int mode = (SystemInfo.isLinux ? mySharedMem.getInt(myModeOffset) : mySharedMem.getShort(myModeOffset)) & LibC.S_MASK;
|
||||
final boolean isSymlink = (mode & LibC.S_IFLNK) == LibC.S_IFLNK;
|
||||
if (isSymlink) {
|
||||
mySharedMem.clear();
|
||||
res = SystemInfo.isLinux ? myLibC.__xstat64(0, path, mySharedMem) : myLibC.stat(path, mySharedMem);
|
||||
if (res != 0) {
|
||||
return FileAttributes.BROKEN_SYMLINK;
|
||||
|
||||
@@ -28,7 +28,6 @@ import com.intellij.util.containers.Stack;
|
||||
import com.intellij.util.io.URLUtil;
|
||||
import com.intellij.util.text.CaseInsensitiveStringHashingStrategy;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
import org.intellij.lang.annotations.RegExp;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -396,20 +395,16 @@ public class FileUtil extends FileUtilRt {
|
||||
|
||||
public static boolean createParentDirs(@NotNull File file) {
|
||||
if (!file.exists()) {
|
||||
String parentDirPath = file.getParent();
|
||||
if (parentDirPath != null) {
|
||||
final File parentFile = new File(parentDirPath);
|
||||
final File parentFile = file.getParentFile();
|
||||
if (parentFile != null) {
|
||||
return createDirectory(parentFile);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean createDirectory(File parentFile) {
|
||||
int parentAttributes = getBooleanAttributes(parentFile);
|
||||
boolean ok = parentAttributes != -1 ? (parentAttributes & (BA_EXISTS | BA_DIRECTORY)) == (BA_EXISTS | BA_DIRECTORY)
|
||||
: parentFile.exists() && parentFile.isDirectory();
|
||||
return ok || parentFile.mkdirs();
|
||||
public static boolean createDirectory(@NotNull File path) {
|
||||
return path.isDirectory() || path.mkdirs();
|
||||
}
|
||||
|
||||
public static boolean createIfDoesntExist(@NotNull File file) {
|
||||
@@ -1008,12 +1003,13 @@ public class FileUtil extends FileUtilRt {
|
||||
@NotNull
|
||||
public static List<File> findFilesByMask(@NotNull Pattern pattern, @NotNull File dir) {
|
||||
final ArrayList<File> found = new ArrayList<File>();
|
||||
for (File file : dir.listFiles()) {
|
||||
if (file.isDirectory()) {
|
||||
found.addAll(findFilesByMask(pattern, file));
|
||||
}
|
||||
else {
|
||||
if (pattern.matcher(file.getName()).matches()) {
|
||||
final File[] files = dir.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
found.addAll(findFilesByMask(pattern, file));
|
||||
}
|
||||
else if (pattern.matcher(file.getName()).matches()) {
|
||||
found.add(file);
|
||||
}
|
||||
}
|
||||
@@ -1024,13 +1020,15 @@ public class FileUtil extends FileUtilRt {
|
||||
@NotNull
|
||||
public static List<File> findFilesOrDirsByMask(@NotNull Pattern pattern, @NotNull File dir) {
|
||||
final ArrayList<File> found = new ArrayList<File>();
|
||||
for (File file : dir.listFiles()) {
|
||||
if (file.isDirectory()) {
|
||||
found.addAll(findFilesOrDirsByMask(pattern, file));
|
||||
}
|
||||
|
||||
if (pattern.matcher(file.getName()).matches()) {
|
||||
found.add(file);
|
||||
final File[] files = dir.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
if (pattern.matcher(file.getName()).matches()) {
|
||||
found.add(file);
|
||||
}
|
||||
if (file.isDirectory()) {
|
||||
found.addAll(findFilesOrDirsByMask(pattern, file));
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
@@ -1039,7 +1037,7 @@ public class FileUtil extends FileUtilRt {
|
||||
/**
|
||||
* Returns empty string for empty path.
|
||||
* First checks whether provided path is a path of a file with sought-for name.
|
||||
* Unless found, checks if provided file was a directory. In this case checks existance
|
||||
* Unless found, checks if provided file was a directory. In this case checks existence
|
||||
* of child files with given names in order "as provided". Finally checks filename among
|
||||
* brother-files of provided. Returns null if nothing found.
|
||||
*
|
||||
@@ -1152,7 +1150,7 @@ public class FileUtil extends FileUtilRt {
|
||||
|
||||
@NotNull
|
||||
public static File createTempDirectory(@NotNull File dir, @NotNull @NonNls String prefix, @Nullable @NonNls String suffix, boolean deleteOnExit) throws IOException {
|
||||
return FileUtilRt.createTempDirectory(dir, prefix, suffix,deleteOnExit);
|
||||
return FileUtilRt.createTempDirectory(dir, prefix, suffix, deleteOnExit);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -1243,58 +1241,6 @@ public class FileUtil extends FileUtilRt {
|
||||
return FileUtilRt.loadBytes(stream, length);
|
||||
}
|
||||
|
||||
// copied from FileSystem: they are package local there
|
||||
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 {}
|
||||
|
||||
private static final Method JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD;
|
||||
private static final Object JAVA_IO_FILESYSTEM;
|
||||
|
||||
// todo[r.sh] use NIO2 API after migration to JDK 7
|
||||
// returns -1 if could not get attributes
|
||||
@FileBooleanAttributes
|
||||
public static int getBooleanAttributes(@NotNull File f) {
|
||||
if (JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD != null) {
|
||||
try {
|
||||
Object flags = JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD.invoke(JAVA_IO_FILESYSTEM, f);
|
||||
//noinspection MagicConstant
|
||||
return ((Integer)flags).intValue();
|
||||
}
|
||||
catch (Exception ignored) { }
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static {
|
||||
Object fs;
|
||||
Method getBooleanAttributes;
|
||||
try {
|
||||
Class<?> fsClass = Class.forName("java.io.FileSystem");
|
||||
Method getFileSystem = fsClass.getMethod("getFileSystem");
|
||||
getFileSystem.setAccessible(true);
|
||||
fs = getFileSystem.invoke(null);
|
||||
getBooleanAttributes = fsClass.getDeclaredMethod("getBooleanAttributes", File.class);
|
||||
if (fs == null || getBooleanAttributes == null) {
|
||||
fs = null;
|
||||
getBooleanAttributes = null;
|
||||
}
|
||||
else {
|
||||
getBooleanAttributes.setAccessible(true);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
fs = null;
|
||||
getBooleanAttributes = null;
|
||||
}
|
||||
JAVA_IO_FILESYSTEM = fs;
|
||||
JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD = getBooleanAttributes;
|
||||
}
|
||||
|
||||
private static final class CompletedFuture<T> implements Future<T> {
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
return false;
|
||||
@@ -1305,9 +1251,11 @@ public class FileUtil extends FileUtilRt {
|
||||
public boolean isDone() {
|
||||
return true;
|
||||
}
|
||||
@Nullable
|
||||
public T get() throws InterruptedException, ExecutionException {
|
||||
return null;
|
||||
}
|
||||
@Nullable
|
||||
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user