diff --git a/platform/platform-tests/testSrc/com/intellij/execution/wsl/WslSyncTest.kt b/platform/platform-tests/testSrc/com/intellij/execution/wsl/WslSyncTest.kt index 44a28ccc2bee..58d9ce029e3f 100644 --- a/platform/platform-tests/testSrc/com/intellij/execution/wsl/WslSyncTest.kt +++ b/platform/platform-tests/testSrc/com/intellij/execution/wsl/WslSyncTest.kt @@ -177,6 +177,8 @@ class WslSyncTest(private val linToWin: Boolean) { val modifyEachFile = 3 val windowsDir = winDirRule.newDirectoryPath() + val executable = "execfile" + val execTxt = "exec.txt" val fileNames = (0..numberOfFiles).map { "$it-по-русски.txt" } val srcDir = if (linToWin) linuxDirAsPath else windowsDir @@ -185,8 +187,13 @@ class WslSyncTest(private val linToWin: Boolean) { for (fileName in fileNames) { srcDir.resolve(fileName).writeText("hello $fileName") } + srcDir.resolve(executable).writeText("#!/bin/sh") + srcDir.resolve(execTxt).writeText(" $executable ") // Must be marked executable on Linux WslSync.syncWslFolders(linuxDirRule.dir, windowsDir, wslRule.wsl, linToWin) + if (!linToWin) { + wslRule.wsl.runCommand("${linuxDirRule.dir}/$executable").getOrThrow() + } val modificationTimes = mutableMapOf() for (fileName in fileNames) { @@ -195,7 +202,7 @@ class WslSyncTest(private val linToWin: Boolean) { Assert.assertEquals("Copied with wrong content", "hello $fileName", file.readText()) modificationTimes[file] = file.lastModified() } - Assert.assertEquals(fileNames.size, dstDir.toFile().list()!!.size) + Assert.assertEquals(fileNames.size + 2, dstDir.toFile().list()!!.size) // + exec files Thread.sleep(1000) // To check modification time diff --git a/platform/wsl-impl/src/com/intellij/execution/wsl/sync/LinuxFileStorage.kt b/platform/wsl-impl/src/com/intellij/execution/wsl/sync/LinuxFileStorage.kt index 15fee41f2681..f26d3623ade2 100644 --- a/platform/wsl-impl/src/com/intellij/execution/wsl/sync/LinuxFileStorage.kt +++ b/platform/wsl-impl/src/com/intellij/execution/wsl/sync/LinuxFileStorage.kt @@ -172,5 +172,9 @@ class LinuxFileStorage(dir: LinuxFilePath, distro: AbstractWslDistribution, filt script.first.delete() } } + + fun markExec(fileToMarkExec: String) { + distro.runCommand("chmod", "+x", "$dir/$fileToMarkExec").getOrThrow() + } } diff --git a/platform/wsl-impl/src/com/intellij/execution/wsl/sync/WslSync.kt b/platform/wsl-impl/src/com/intellij/execution/wsl/sync/WslSync.kt index 60ad9787591e..f53a5df0f1dd 100644 --- a/platform/wsl-impl/src/com/intellij/execution/wsl/sync/WslSync.kt +++ b/platform/wsl-impl/src/com/intellij/execution/wsl/sync/WslSync.kt @@ -9,11 +9,16 @@ import java.nio.file.Path import java.util.concurrent.CompletableFuture.runAsync import java.util.concurrent.CompletableFuture.supplyAsync import java.util.concurrent.Future +import kotlin.io.path.exists +import kotlin.io.path.readText /** * When copying files in parallel we must split them to the several chunks (each chunk is separate .tar file). * No reason to have less than [MIN_CHUNK_SIZE] files in one chunk: two files shouldn't be split to two chunks + * + * If source is windows and top level ``exec.txt`` file exists, it should contain list of top level files to mark +x on Linux side + * (in case your helper needs to be executable) */ private const val MIN_CHUNK_SIZE = 1000 @@ -45,6 +50,13 @@ class WslSync private constructor(private val source: File } else { WslSync(win, lin) + val execFile = windowsDir.resolve("exec.txt") + if (execFile.exists()) { + // TODO: Support non top level files + for(fileToMarkExec in execFile.readText().split(Regex("\\s+")).map { it.trim() }) { + lin.markExec(fileToMarkExec) + } + } } } } diff --git a/python/helpers/exec.txt b/python/helpers/exec.txt new file mode 100644 index 000000000000..e69de29bb2d1