From 08e893528cafbf9a8cf99d418a0f2c1a16c3afef Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 8 Dec 2011 17:55:46 +0100 Subject: [PATCH] [davdeev] Symlink support reloaded --- .../vfs/newvfs/impl/SymlinkDirectory.java | 68 ++++++++++++++++--- .../vfs/newvfs/impl/VirtualDirectoryImpl.java | 4 +- 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/SymlinkDirectory.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/SymlinkDirectory.java index 28dfa5d2226e..dc12c2d4b485 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/SymlinkDirectory.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/SymlinkDirectory.java @@ -15,9 +15,11 @@ */ package com.intellij.openapi.vfs.newvfs.impl; +import com.intellij.openapi.util.AtomicNotNullLazyValue; import com.intellij.openapi.util.NullableComputable; import com.intellij.openapi.util.RecursionManager; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.newvfs.NewVirtualFile; import com.intellij.openapi.vfs.newvfs.NewVirtualFileSystem; import com.intellij.openapi.vfs.newvfs.VfsImplUtil; import org.jetbrains.annotations.NotNull; @@ -25,28 +27,72 @@ import org.jetbrains.annotations.Nullable; /** * @author Dmitry Avdeev - * Date: 10/31/11 + * @since 31.10.2011 */ +@SuppressWarnings("NonSynchronizedMethodOverridesSynchronizedMethod") public class SymlinkDirectory extends VirtualDirectoryImpl { + private final AtomicNotNullLazyValue myTarget = new AtomicNotNullLazyValue() { + @NotNull + @Override + protected VirtualDirectoryImpl compute() { + final String path = getFileSystem().resolveSymLink(SymlinkDirectory.this); + VirtualFile file = null; + if (path != null) { + file = findFile(path, false); + } + if (file == SymlinkDirectory.this && file != null) { + final VirtualFile parent = file.getParent(); + if (parent instanceof VirtualDirectoryImpl) { + ((VirtualDirectoryImpl)parent).removeChild(file); + file = findFile(path, true); + } + } + return file instanceof VirtualDirectoryImpl ? (VirtualDirectoryImpl)file : new VirtualDirectoryImpl("foo", SymlinkDirectory.this, getFileSystem(), 0); + } - @Nullable - private final VirtualFile myTarget; + @Nullable + private VirtualFile findFile(final String path, final boolean refresh) { + return RecursionManager.doPreventingRecursion(SymlinkDirectory.this, false, new NullableComputable() { + @Override + public VirtualFile compute() { + return refresh ? VfsImplUtil.refreshAndFindFileByPath(getFileSystem(), path) : VfsImplUtil.findFileByPath(getFileSystem(), path); + } + }); + } + }; public SymlinkDirectory(@NotNull String name, final VirtualDirectoryImpl parent, @NotNull final NewVirtualFileSystem fs, final int id) { super(name, parent, fs, id); - final String path = fs.resolveSymLink(this); + } - myTarget = path == null ? null : RecursionManager.doPreventingRecursion("", false, new NullableComputable() { - @Override - public VirtualFile compute() { - return VfsImplUtil.findFileByPath(getFileSystem(), path); - } - }); + @Override + public VirtualFileSystemEntry findChild(@NotNull String name) { + return myTarget.getValue().findChild(name); + } + + @Override + public NewVirtualFile findChildIfCached(@NotNull String name) { + return myTarget.getValue().findChildIfCached(name); + } + + @Override + public NewVirtualFile findChildById(int id) { + return myTarget.getValue().findChildById(id); + } + + @Override + public NewVirtualFile findChildByIdIfCached(int id) { + return myTarget.getValue().findChildByIdIfCached(id); + } + + @Override + public NewVirtualFile refreshAndFindChild(@NotNull String name) { + return myTarget.getValue().refreshAndFindChild(name); } @NotNull @Override public VirtualFile[] getChildren() { - return myTarget == null ? VirtualFile.EMPTY_ARRAY : myTarget.getChildren(); + return myTarget.getValue().getChildren(); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java index 1f2a85384360..128963c96843 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java @@ -63,6 +63,8 @@ import java.util.*; * @author max */ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { + private static final boolean ALT_SYMLINK_HANDLING = "true".equals(System.getProperty("idea.io.alt.symlink")); + private static final VirtualFileSystemEntry NULL_VIRTUAL_FILE = new VirtualFileImpl("*?;%NULL", null, -42); private final NewVirtualFileSystem myFS; @@ -165,7 +167,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { final VirtualFileSystemEntry child; final NewVirtualFileSystem fs = getFileSystem(); if (PersistentFS.isDirectory(id)) { - child = /*PersistentFS.isSymLink(id) ? new SymlinkDirectory(name, this, fs, id) :*/ new VirtualDirectoryImpl(name, this, fs, id); + child = ALT_SYMLINK_HANDLING && PersistentFS.isSymLink(id) ? new SymlinkDirectory(name, this, fs, id) : new VirtualDirectoryImpl(name, this, fs, id); } else { child = new VirtualFileImpl(name, this, id);