From 5a78fba240b08799aafa25351fff12bf7d6b258e Mon Sep 17 00:00:00 2001 From: patrickpircher Date: Fri, 10 May 2024 17:00:45 +0200 Subject: [PATCH 1/2] wip --- .../kotlin/com/wsl/symlinks/vfs/WslVirtualFileSystem.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/com/wsl/symlinks/vfs/WslVirtualFileSystem.kt b/src/main/kotlin/com/wsl/symlinks/vfs/WslVirtualFileSystem.kt index 2477e0e..8c5ccb3 100644 --- a/src/main/kotlin/com/wsl/symlinks/vfs/WslVirtualFileSystem.kt +++ b/src/main/kotlin/com/wsl/symlinks/vfs/WslVirtualFileSystem.kt @@ -12,7 +12,8 @@ import com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl import com.intellij.openapi.vfs.newvfs.impl.StubVirtualFile import com.intellij.platform.workspace.storage.url.VirtualFileUrl import com.intellij.util.io.URLUtil -import java.io.* +import sun.nio.fs.AbstractFileSystemProvider +import sun.nio.fs.DefaultFileSystemProvider import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.LinkedBlockingQueue import java.util.concurrent.TimeUnit @@ -20,12 +21,17 @@ import java.util.concurrent.locks.ReentrantLock import kotlin.concurrent.thread import kotlin.concurrent.withLock +class WslfsFileSystemProvider: DefaultFileSystemProvider() { + +} + class StartupListener: AppLifecycleListener { override fun appFrameCreated(commandLineArgs: MutableList) { val point = VirtualFileSystem.EP_NAME.point val extension = point.extensionList.find { it.instance is LocalFileSystemImpl && it.instance.javaClass.name.contains("LocalFileSystemImpl") } point.unregisterExtension(extension) + System.setProperty("java.nio.file.spi.DefaultFileSystemProvider", "com.wsl.symlinks.vfs.WslfsFileSystemProvider"); } } From 929d4c659d7cf5a40721d2e08e505df337698b0e Mon Sep 17 00:00:00 2001 From: patrick Date: Mon, 13 May 2024 12:52:06 +0200 Subject: [PATCH 2/2] fail --- build.gradle.kts | 3 + .../wsl/symlinks/vfs/WslVirtualFileSystem.kt | 148 ++++++++++++++++-- 2 files changed, 137 insertions(+), 14 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index a269b81..04304ca 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,6 +11,9 @@ plugins { id("org.jetbrains.intellij") version "1.17.2" } +tasks.runIde { + jvmArgs("java.nio.file.spi.DefaultFileSystemProvider=com.wsl.symlinks.vfs.WslfsFileSystemProvider") +} group = "com.wsl.symlinks" version = "2024.1.5" diff --git a/src/main/kotlin/com/wsl/symlinks/vfs/WslVirtualFileSystem.kt b/src/main/kotlin/com/wsl/symlinks/vfs/WslVirtualFileSystem.kt index 8c5ccb3..2a983fc 100644 --- a/src/main/kotlin/com/wsl/symlinks/vfs/WslVirtualFileSystem.kt +++ b/src/main/kotlin/com/wsl/symlinks/vfs/WslVirtualFileSystem.kt @@ -12,40 +12,154 @@ import com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl import com.intellij.openapi.vfs.newvfs.impl.StubVirtualFile import com.intellij.platform.workspace.storage.url.VirtualFileUrl import com.intellij.util.io.URLUtil -import sun.nio.fs.AbstractFileSystemProvider -import sun.nio.fs.DefaultFileSystemProvider +import com.intellij.util.lang.PathClassLoader +import java.io.* +import java.net.URI +import java.nio.channels.SeekableByteChannel +import java.nio.file.* +import java.nio.file.attribute.BasicFileAttributes +import java.nio.file.attribute.FileAttribute +import java.nio.file.attribute.FileAttributeView +import java.nio.file.spi.FileSystemProvider import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.LinkedBlockingQueue import java.util.concurrent.TimeUnit import java.util.concurrent.locks.ReentrantLock import kotlin.concurrent.thread import kotlin.concurrent.withLock +import kotlin.io.path.absolutePathString -class WslfsFileSystemProvider: DefaultFileSystemProvider() { +class WslfsFileSystemProvider(val provider: FileSystemProvider): FileSystemProvider() { + val fs = WslVirtualFileSystem() + + class WslAttrs(val vfile: VirtualFile, attrs: BasicFileAttributes): BasicFileAttributes by attrs { + override fun isSymbolicLink(): Boolean { + val provider = WslSymlinksProvider.getWslSymlinksProviders(vfile.getWSLDistribution()!!) + return provider.isWslSymlink(vfile) + } + } + + override fun getScheme(): String { + return provider.scheme + } + + override fun newFileSystem(uri: URI?, env: MutableMap?): FileSystem { + return provider.newFileSystem(uri, env) + } + + override fun getFileSystem(uri: URI?): FileSystem { + return provider.getFileSystem(uri) + } + + override fun getPath(uri: URI?): Path { + return provider.getPath(uri) + } + + override fun newByteChannel( + path: Path?, + options: MutableSet?, + vararg attrs: FileAttribute<*>? + ): SeekableByteChannel { + return provider.newByteChannel(path, options, *attrs) + } + + override fun newDirectoryStream(dir: Path?, filter: DirectoryStream.Filter?): DirectoryStream { + return provider.newDirectoryStream(dir, filter) + } + + override fun createDirectory(dir: Path?, vararg attrs: FileAttribute<*>?) { + return provider.createDirectory(dir, *attrs) + } + + override fun delete(path: Path?) { + return provider.delete(path) + } + + override fun copy(source: Path?, target: Path?, vararg options: CopyOption?) { + return provider.copy(source, target, *options) + } + + override fun move(source: Path?, target: Path?, vararg options: CopyOption?) { + return provider.move(source, target, *options) + } + + override fun isSameFile(path: Path?, path2: Path?): Boolean { + return provider.isSameFile(path, path2) + } + + override fun isHidden(path: Path?): Boolean { + return provider.isHidden(path) + } + + override fun getFileStore(path: Path?): FileStore { + return provider.getFileStore(path) + } + + override fun checkAccess(path: Path?, vararg modes: AccessMode?) { + return provider.checkAccess(path, *modes) + } + + override fun getFileAttributeView( + path: Path?, + type: Class?, + vararg options: LinkOption? + ): V { + return provider.getFileAttributeView(path, type, *options) + } + + override fun readAttributes( + path: Path, + type: Class, + vararg options: LinkOption? + ): A { + val attrs = provider.readAttributes(path, type, *options) + val vfile = FakeVirtualFile(path.absolutePathString(), null, fs) + if (vfile.isFromWSL()) { + return WslAttrs(vfile, attrs as BasicFileAttributes) as A + } + return attrs + } + + override fun readAttributes( + path: Path, + attributes: String, + vararg options: LinkOption + ): MutableMap { + val attrs = provider.readAttributes(path, attributes, *options) + val vfile = FakeVirtualFile(path.absolutePathString(), null, fs) + if (vfile.isFromWSL()) { + + } + return attrs + } + + override fun setAttribute(path: Path?, attribute: String?, value: Any?, vararg options: LinkOption?) { + return provider.setAttribute(path, attribute, value, *options) + } } class StartupListener: AppLifecycleListener { override fun appFrameCreated(commandLineArgs: MutableList) { + System.setProperty("java.nio.file.spi.DefaultFileSystemProvider", "com.wsl.symlinks.vfs.WslfsFileSystemProvider"); val point = VirtualFileSystem.EP_NAME.point val extension = point.extensionList.find { it.instance is LocalFileSystemImpl && it.instance.javaClass.name.contains("LocalFileSystemImpl") } point.unregisterExtension(extension) - System.setProperty("java.nio.file.spi.DefaultFileSystemProvider", "com.wsl.symlinks.vfs.WslfsFileSystemProvider"); } } -class FakeVirtualFile(val resPath: String, val vfile: VirtualFile, val fs: WslVirtualFileSystem): StubVirtualFile(fs) { +class FakeVirtualFile(val resPath: String, val vfile: VirtualFile?, val fs: WslVirtualFileSystem): StubVirtualFile(fs) { override fun getPath(): String { return resPath } override fun getLength(): Long { - return fs.getAttributes(vfile)?.length ?: 0 + return vfile?.let { fs.getAttributes(it) }?.length ?: 0 } override fun getParent(): VirtualFile? { - return vfile.parent + return vfile?.parent } } @@ -71,6 +185,7 @@ fun Boolean.ifFalse(value: T): T? { } + class WslSymlinksProvider(distro: String) { val LOGGER = Logger.getInstance(WslSymlinksProvider::class.java) @@ -105,7 +220,6 @@ class WslSymlinksProvider(distro: String) { init { LOGGER.info("starting WslSymlinksProvider for distro: $distro") - fun setupProcess() { val bash = {}.javaClass.getResource("/files.sh")?.readText()!! val location = "\\\\wsl.localhost\\$distro\\var\\tmp\\intellij-idea-wsl-symlinks.sh" @@ -226,14 +340,23 @@ class WslSymlinksProvider(distro: String) { } return false } + + companion object { + private var wslSymlinksProviders: MutableMap = HashMap() + fun getWslSymlinksProviders(distro: String): WslSymlinksProvider { + if (!this.wslSymlinksProviders.containsKey(distro)) { + this.wslSymlinksProviders[distro] = WslSymlinksProvider(distro) + } + return this.wslSymlinksProviders[distro]!! + } + } } class WslVirtualFileSystem: LocalFileSystemImpl() { val LOGGER = Logger.getInstance(WslVirtualFileSystem::class.java) - private var wslSymlinksProviders: MutableMap = HashMap() init { - + System.setProperty("java.nio.file.spi.DefaultFileSystemProvider", "sun.nio.fs.WindowsFileSystemProvider,com.wsl.symlinks.vfs.WslfsFileSystemProvider"); } override fun getProtocol(): String { @@ -242,10 +365,7 @@ class WslVirtualFileSystem: LocalFileSystemImpl() { fun getWslSymlinksProviders(file: VirtualFile): WslSymlinksProvider { val distro = file.getWSLDistribution()!! - if (!this.wslSymlinksProviders.containsKey(distro)) { - this.wslSymlinksProviders[distro] = WslSymlinksProvider(distro) - } - return this.wslSymlinksProviders[distro]!! + return WslSymlinksProvider.getWslSymlinksProviders(distro) } fun getRealPath(file: VirtualFile): String {