mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
symlink support in vfs & SOE protection
This commit is contained in:
@@ -20,7 +20,11 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class VfsUtilCore {
|
||||
/**
|
||||
@@ -151,4 +155,29 @@ public class VfsUtilCore {
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
public static void visitChildrenRecursively(@NotNull VirtualFile file, VirtualFileVisitor visitor) {
|
||||
visitChildrenRecursively(file, visitor, null);
|
||||
}
|
||||
|
||||
private static void visitChildrenRecursively(@NotNull VirtualFile file,
|
||||
VirtualFileVisitor visitor,
|
||||
@Nullable Set<VirtualFile> visitedSymlinks) {
|
||||
|
||||
if (!visitor.visitFile(file)) return;
|
||||
if (file.isSymLink()) {
|
||||
if (visitedSymlinks == null) {
|
||||
visitedSymlinks = new HashSet<VirtualFile>();
|
||||
}
|
||||
if (!visitedSymlinks.add(file)) {
|
||||
visitor.afterChildrenVisited(file);
|
||||
return;
|
||||
}
|
||||
}
|
||||
VirtualFile[] children = file.getChildren();
|
||||
for (VirtualFile child : children) {
|
||||
visitChildrenRecursively(child, visitor, visitedSymlinks);
|
||||
}
|
||||
visitor.afterChildrenVisited(file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,6 +212,11 @@ public abstract class VirtualFile extends UserDataHolderBase implements Modifica
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String resolveSymLink() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this file is a special (e.g. FIFO or device) file.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.vfs;
|
||||
|
||||
/**
|
||||
* @author Dmitry Avdeev
|
||||
* Date: 10/31/11
|
||||
*/
|
||||
public abstract class VirtualFileVisitor {
|
||||
|
||||
public abstract boolean visitFile(VirtualFile file);
|
||||
|
||||
public void afterChildrenVisited(VirtualFile file) {}
|
||||
}
|
||||
@@ -353,7 +353,7 @@ public class DirectoryIndexImpl extends DirectoryIndex implements ProjectCompone
|
||||
}
|
||||
|
||||
if (!parentInfo.getOrderEntries().isEmpty()) {
|
||||
state.fillMapWithOrderEntries(file, parentInfo.getOrderEntries(), null, null, null, parentInfo, null);
|
||||
state.fillMapWithOrderEntries(file, parentInfo.getOrderEntries(), null, null, null, parentInfo);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
@@ -427,29 +427,59 @@ public class DirectoryIndexImpl extends DirectoryIndex implements ProjectCompone
|
||||
return info;
|
||||
}
|
||||
|
||||
private void fillMapWithModuleContent(VirtualFile dir, Module module, VirtualFile contentRoot) {
|
||||
if (isExcluded(contentRoot, dir)) return;
|
||||
if (isIgnored(dir)) return;
|
||||
private void fillMapWithModuleContent(VirtualFile root, final Module module, final VirtualFile contentRoot) {
|
||||
|
||||
DirectoryInfo info = getOrCreateDirInfo(dir);
|
||||
VfsUtilCore.visitChildrenRecursively(root, new DirectoryVisitor() {
|
||||
|
||||
@Override
|
||||
protected DirectoryInfo updateInfo(VirtualFile file) {
|
||||
if (isExcluded(contentRoot, file)) return null;
|
||||
if (isIgnored(file)) return null;
|
||||
|
||||
if (info.module != null) { // module contents overlap
|
||||
DirectoryInfo parentInfo = myDirToInfoMap.get(dir.getParent());
|
||||
if (parentInfo == null || !info.module.equals(parentInfo.module)) return; // content of another module is below this module's content
|
||||
}
|
||||
DirectoryInfo info = getOrCreateDirInfo(file);
|
||||
|
||||
VirtualFile[] children = dir.getChildren();
|
||||
for (VirtualFile child : children) {
|
||||
if (child.isDirectory()) {
|
||||
fillMapWithModuleContent(child, module, contentRoot);
|
||||
if (info.module != null) { // module contents overlap
|
||||
DirectoryInfo parentInfo = myDirToInfoMap.get(file.getParent());
|
||||
if (parentInfo == null || !info.module.equals(parentInfo.module)) return null;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
// important to change module AFTER processing children - to handle overlapping modules
|
||||
info.module = module;
|
||||
info.contentRoot = contentRoot;
|
||||
@Override
|
||||
protected void afterChildrenVisited(DirectoryInfo info) {
|
||||
info.module = module;
|
||||
info.contentRoot = contentRoot;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private abstract class DirectoryVisitor extends VirtualFileVisitor {
|
||||
|
||||
private Stack<DirectoryInfo> myDirectoryInfoStack = new Stack<DirectoryInfo>();
|
||||
|
||||
@Override
|
||||
public boolean visitFile(VirtualFile file) {
|
||||
if (!file.isDirectory()) return false;
|
||||
DirectoryInfo info = updateInfo(file);
|
||||
if (info != null) {
|
||||
myDirectoryInfoStack.push(info);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterChildrenVisited(VirtualFile file) {
|
||||
afterChildrenVisited(myDirectoryInfoStack.pop());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract DirectoryInfo updateInfo(VirtualFile file);
|
||||
|
||||
protected void afterChildrenVisited(DirectoryInfo info) {}
|
||||
}
|
||||
|
||||
private boolean isExcluded(VirtualFile root, VirtualFile dir) {
|
||||
Set<String> excludes = myExcludeRootsMap.get(root);
|
||||
return excludes != null && excludes.contains(dir.getUrl());
|
||||
@@ -494,28 +524,45 @@ public class DirectoryIndexImpl extends DirectoryIndex implements ProjectCompone
|
||||
}
|
||||
}
|
||||
|
||||
private void fillMapWithModuleSource(VirtualFile dir, Module module, String packageName, VirtualFile sourceRoot, boolean isTestSource) {
|
||||
DirectoryInfo info = myDirToInfoMap.get(dir);
|
||||
if (info == null) return;
|
||||
if (!module.equals(info.module)) return;
|
||||
private void fillMapWithModuleSource(final VirtualFile dir, final Module module, final String packageName, final VirtualFile sourceRoot, final boolean isTestSource) {
|
||||
|
||||
VfsUtilCore.visitChildrenRecursively(dir, new DirectoryVisitor() {
|
||||
|
||||
private Stack<String> myPackages = new Stack<String>();
|
||||
|
||||
if (info.isInModuleSource) { // module sources overlap
|
||||
String definedPackage = myDirToPackageName.get(dir);
|
||||
if (definedPackage != null && definedPackage.length() == 0) return; // another source root starts here
|
||||
}
|
||||
@Override
|
||||
protected DirectoryInfo updateInfo(VirtualFile file) {
|
||||
DirectoryInfo info = myDirToInfoMap.get(file);
|
||||
if (info == null) return null;
|
||||
if (!module.equals(info.module)) return null;
|
||||
|
||||
info.isInModuleSource = true;
|
||||
info.isTestSource = isTestSource;
|
||||
info.sourceRoot = sourceRoot;
|
||||
setPackageName(dir, packageName);
|
||||
if (info.isInModuleSource) { // module sources overlap
|
||||
String definedPackage = myDirToPackageName.get(file);
|
||||
if (definedPackage != null && definedPackage.length() == 0) return null; // another source root starts here
|
||||
}
|
||||
|
||||
VirtualFile[] children = dir.getChildren();
|
||||
for (VirtualFile child : children) {
|
||||
if (child.isDirectory()) {
|
||||
String childPackageName = getPackageNameForSubdir(packageName, child.getName());
|
||||
fillMapWithModuleSource(child, module, childPackageName, sourceRoot, isTestSource);
|
||||
info.isInModuleSource = true;
|
||||
info.isTestSource = isTestSource;
|
||||
info.sourceRoot = sourceRoot;
|
||||
|
||||
String currentPackage;
|
||||
if (myPackages.isEmpty()) {
|
||||
currentPackage = packageName;
|
||||
}
|
||||
else {
|
||||
currentPackage = getPackageNameForSubdir(myPackages.peek(), file.getName());
|
||||
}
|
||||
myPackages.push(currentPackage);
|
||||
setPackageName(file, currentPackage);
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterChildrenVisited(DirectoryInfo info) {
|
||||
super.afterChildrenVisited(info);
|
||||
myPackages.pop();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initLibrarySources(Module module, ProgressIndicator progress) {
|
||||
@@ -623,7 +670,7 @@ public class DirectoryIndexImpl extends DirectoryIndex implements ProjectCompone
|
||||
|
||||
VirtualFile[] sourceRoots = orderEntry.getFiles(OrderRootType.SOURCES);
|
||||
for (VirtualFile sourceRoot : sourceRoots) {
|
||||
fillMapWithOrderEntries(sourceRoot, oneEntryList, entryModule, null, null, null, null);
|
||||
fillMapWithOrderEntries(sourceRoot, oneEntryList, entryModule, null, null, null);
|
||||
}
|
||||
}
|
||||
else if (orderEntry instanceof LibraryOrderEntry || orderEntry instanceof JdkOrderEntry) {
|
||||
@@ -645,19 +692,19 @@ public class DirectoryIndexImpl extends DirectoryIndex implements ProjectCompone
|
||||
for (Map.Entry<VirtualFile, Collection<OrderEntry>> mapEntry : depEntries.entrySet()) {
|
||||
final VirtualFile vRoot = mapEntry.getKey();
|
||||
final Collection<OrderEntry> entries = mapEntry.getValue();
|
||||
fillMapWithOrderEntries(vRoot, entries, null, null, null, null, null);
|
||||
fillMapWithOrderEntries(vRoot, entries, null, null, null, null);
|
||||
}
|
||||
|
||||
for (Map.Entry<VirtualFile, Collection<OrderEntry>> mapEntry : libClassRootEntries.entrySet()) {
|
||||
final VirtualFile vRoot = mapEntry.getKey();
|
||||
final Collection<OrderEntry> entries = mapEntry.getValue();
|
||||
fillMapWithOrderEntries(vRoot, entries, null, vRoot, null, null, null);
|
||||
fillMapWithOrderEntries(vRoot, entries, null, vRoot, null, null);
|
||||
}
|
||||
|
||||
for (Map.Entry<VirtualFile, Collection<OrderEntry>> mapEntry : libSourceRootEntries.entrySet()) {
|
||||
final VirtualFile vRoot = mapEntry.getKey();
|
||||
final Collection<OrderEntry> entries = mapEntry.getValue();
|
||||
fillMapWithOrderEntries(vRoot, entries, null, null, vRoot, null, null);
|
||||
fillMapWithOrderEntries(vRoot, entries, null, null, vRoot, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -690,41 +737,50 @@ public class DirectoryIndexImpl extends DirectoryIndex implements ProjectCompone
|
||||
}
|
||||
}
|
||||
|
||||
private void fillMapWithOrderEntries(VirtualFile dir,
|
||||
Collection<OrderEntry> orderEntries,
|
||||
Module module,
|
||||
VirtualFile libraryClassRoot,
|
||||
VirtualFile librarySourceRoot,
|
||||
DirectoryInfo parentInfo,
|
||||
final List<OrderEntry> oldParentEntries) {
|
||||
if (isIgnored(dir)) return;
|
||||
private void fillMapWithOrderEntries(final VirtualFile root,
|
||||
final Collection<OrderEntry> orderEntries,
|
||||
final Module module,
|
||||
final VirtualFile libraryClassRoot,
|
||||
final VirtualFile librarySourceRoot,
|
||||
final DirectoryInfo parentInfo) {
|
||||
|
||||
VfsUtilCore.visitChildrenRecursively(root, new DirectoryVisitor() {
|
||||
|
||||
DirectoryInfo info = myDirToInfoMap.get(dir); // do not create it here!
|
||||
if (info == null) return;
|
||||
private Stack<List<OrderEntry>> myEntries = new Stack<List<OrderEntry>>();
|
||||
|
||||
if (module != null) {
|
||||
if (info.module != module) return;
|
||||
if (!info.isInModuleSource) return;
|
||||
}
|
||||
else if (libraryClassRoot != null) {
|
||||
if (info.libraryClassRoot != libraryClassRoot) return;
|
||||
if (info.isInModuleSource) return;
|
||||
}
|
||||
else if (librarySourceRoot != null) {
|
||||
if (!info.isInLibrarySource) return;
|
||||
if (info.sourceRoot != librarySourceRoot) return;
|
||||
if (info.libraryClassRoot != null) return;
|
||||
}
|
||||
@Override
|
||||
protected DirectoryInfo updateInfo(VirtualFile dir) {
|
||||
if (isIgnored(dir)) return null;
|
||||
|
||||
final List<OrderEntry> oldEntries = info.getOrderEntries();
|
||||
info.addOrderEntries(orderEntries, parentInfo, oldParentEntries);
|
||||
DirectoryInfo info = myDirToInfoMap.get(dir); // do not create it here!
|
||||
if (info == null) return null;
|
||||
|
||||
final VirtualFile[] children = dir.getChildren();
|
||||
for (VirtualFile child : children) {
|
||||
if (child.isDirectory()) {
|
||||
fillMapWithOrderEntries(child, orderEntries, module, libraryClassRoot, librarySourceRoot, info, oldEntries);
|
||||
if (module != null) {
|
||||
if (info.module != module) return null;
|
||||
if (!info.isInModuleSource) return null;
|
||||
}
|
||||
else if (libraryClassRoot != null) {
|
||||
if (info.libraryClassRoot != libraryClassRoot) return null;
|
||||
if (info.isInModuleSource) return null;
|
||||
}
|
||||
else if (librarySourceRoot != null) {
|
||||
if (!info.isInLibrarySource) return null;
|
||||
if (info.sourceRoot != librarySourceRoot) return null;
|
||||
if (info.libraryClassRoot != null) return null;
|
||||
}
|
||||
|
||||
List<OrderEntry> oldParentEntries = myEntries.isEmpty() ? null : myEntries.peek();
|
||||
final List<OrderEntry> oldEntries = info.getOrderEntries();
|
||||
myEntries.push(oldEntries);
|
||||
info.addOrderEntries(orderEntries, parentInfo, oldParentEntries);
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterChildrenVisited(DirectoryInfo info) {
|
||||
myEntries.pop();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void doInitialize(boolean reverseAllSets/* for testing order independence*/) {
|
||||
|
||||
@@ -17,26 +17,34 @@
|
||||
package com.intellij.openapi.roots.impl;
|
||||
|
||||
import com.intellij.openapi.roots.ContentIterator;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileFilter;
|
||||
import com.intellij.openapi.vfs.VirtualFileVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class FileIndexImplUtil {
|
||||
private FileIndexImplUtil() {
|
||||
}
|
||||
|
||||
public static boolean iterateRecursively(@NotNull VirtualFile root, @NotNull VirtualFileFilter filter, @NotNull ContentIterator iterator){
|
||||
if (!root.isValid() || !filter.accept(root)) return true;
|
||||
public static boolean iterateRecursively(@NotNull final VirtualFile root, @NotNull final VirtualFileFilter filter, @NotNull final ContentIterator iterator){
|
||||
|
||||
if (!iterator.processFile(root)) return false;
|
||||
try {
|
||||
VfsUtilCore.visitChildrenRecursively(root, new VirtualFileVisitor() {
|
||||
@Override
|
||||
public boolean visitFile(VirtualFile file) {
|
||||
if (!file.isValid() || !filter.accept(file)) return true;
|
||||
|
||||
if (root.isDirectory()){
|
||||
VirtualFile[] children = root.getChildren();
|
||||
for (VirtualFile child : children) {
|
||||
if (!iterateRecursively(child, filter, iterator)) return false;
|
||||
}
|
||||
if (!iterator.processFile(file)) throw new StopItException();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
catch (StopItException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static class StopItException extends RuntimeException {}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ public interface FileSystemInterface {
|
||||
void setWritable(@NotNull VirtualFile file, boolean writableFlag) throws IOException;
|
||||
|
||||
boolean isSymLink(@NotNull VirtualFile file);
|
||||
@Nullable
|
||||
String resolveSymLink(@NotNull VirtualFile file);
|
||||
|
||||
boolean isSpecialFile(@NotNull VirtualFile file);
|
||||
|
||||
|
||||
@@ -57,6 +57,11 @@ public abstract class NewVirtualFileSystem extends VirtualFileSystem implements
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolveSymLink(@NotNull VirtualFile file) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpecialFile(@NotNull final VirtualFile file) {
|
||||
return false;
|
||||
|
||||
@@ -185,6 +185,11 @@ public class JarHandler extends JarHandlerBase implements FileSystemInterface {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolveSymLink(@NotNull VirtualFile file) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpecialFile(@NotNull VirtualFile file) {
|
||||
return false;
|
||||
|
||||
+5
@@ -178,6 +178,11 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
|
||||
return SymLinkUtil.isSymLink(file.getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolveSymLink(@NotNull VirtualFile file) {
|
||||
return SymLinkUtil.resolveSymLink(file.getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpecialFile(@NotNull final VirtualFile file) {
|
||||
final File ioFile = convertToIOFile(file);
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.vfs.newvfs.impl;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.NewVirtualFileSystem;
|
||||
import com.intellij.openapi.vfs.newvfs.VfsImplUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Dmitry Avdeev
|
||||
* Date: 10/31/11
|
||||
*/
|
||||
public class SymlinkDirectory extends VirtualDirectoryImpl {
|
||||
|
||||
@Nullable
|
||||
private final VirtualFile myTarget;
|
||||
|
||||
public SymlinkDirectory(@NotNull String name, final VirtualDirectoryImpl parent, @NotNull NewVirtualFileSystem fs, final int id) {
|
||||
super(name, parent, fs, id);
|
||||
String path = fs.resolveSymLink(this);
|
||||
myTarget = path == null ? null : VfsImplUtil.findFileByPath(fs, path);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public VirtualFile[] getChildren() {
|
||||
return myTarget == null ? VirtualFile.EMPTY_ARRAY : myTarget.getChildren();
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -68,7 +68,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
|
||||
private final NewVirtualFileSystem myFS;
|
||||
|
||||
// guarded by this
|
||||
private Object myChildren; // Either HashMap<String, VFile> or VFile[]
|
||||
protected Object myChildren; // Either HashMap<String, VFile> or VFile[]
|
||||
|
||||
public VirtualDirectoryImpl(@NotNull String name, final VirtualDirectoryImpl parent, @NotNull NewVirtualFileSystem fs, final int id) {
|
||||
super(name, parent, id);
|
||||
@@ -165,7 +165,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
|
||||
final VirtualFileSystemEntry child;
|
||||
final NewVirtualFileSystem fs = getFileSystem();
|
||||
if (PersistentFS.isDirectory(id)) {
|
||||
child = new VirtualDirectoryImpl(name, this, fs, id);
|
||||
child = PersistentFS.isSymLink(id) ? new SymlinkDirectory(name, this, fs, id) : new VirtualDirectoryImpl(name, this, fs, id);
|
||||
}
|
||||
else {
|
||||
child = new VirtualFileImpl(name, this, id);
|
||||
|
||||
+11
-3
@@ -24,9 +24,7 @@ import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.ex.ApplicationEx;
|
||||
import com.intellij.openapi.components.ApplicationComponent;
|
||||
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.*;
|
||||
import com.intellij.openapi.util.io.BufferExposingByteArrayInputStream;
|
||||
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
|
||||
import com.intellij.openapi.util.io.ByteSequence;
|
||||
@@ -322,6 +320,11 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
|
||||
return (FSRecords.getFlags(id) & IS_DIRECTORY_FLAG) != 0;
|
||||
}
|
||||
|
||||
public static boolean isSymLink(final int id) {
|
||||
assert id > 0;
|
||||
return (FSRecords.getFlags(id) & IS_SYMLINK) != 0;
|
||||
}
|
||||
|
||||
private static int getParent(final int id) {
|
||||
assert id > 0;
|
||||
return FSRecords.getParent(id);
|
||||
@@ -363,6 +366,11 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
|
||||
return (FSRecords.getFlags(getFileId(file)) & IS_SYMLINK) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolveSymLink(@NotNull VirtualFile file) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpecialFile(@NotNull VirtualFile file) {
|
||||
return (FSRecords.getFlags(getFileId(file)) & IS_SPECIAL) != 0;
|
||||
|
||||
Reference in New Issue
Block a user